Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

자동 채점 기능을 기획하고 개발 이슈를 정리한다. #591

Open
1 task done
woowahan-pjs opened this issue Aug 8, 2022 · 4 comments
Open
1 task done
Assignees
Labels
디자인 Improvements or additions to documentation

Comments

@woowahan-pjs
Copy link
Contributor

woowahan-pjs commented Aug 8, 2022

  1. 보안과 관리 상의 이유로 테스트 케이스를 공개하지 않는다.
  2. 리소스 낭비를 피하기 위해 GitHub에 PR을 등록하면 자동으로 점수가 매겨지는 상황이 없어야 한다.
  3. 채점은 플랫폼에 과제를 제출한 후 이루어진다.
    • 예제 테스트 케이스가 통과했는지 확인할 수 있어야 한다.
  4. zip 파일을 제출하거나 개인 저장소를 제출하는 기능은 나중에 고려한다.
  5. 부정행위에 대한 별도의 정책을 세운다.

참고 자료

관련 이슈

@woowahan-pjs woowahan-pjs added the 디자인 Improvements or additions to documentation label Aug 8, 2022
@woowapark
Copy link
Contributor

채점 코드가 실행되는 시점

  • 아래 2가지 경우를 모두 대응할 수 있으면 좋을듯
    • 1 지원자가 과제를 최종 제출하는 시점에 바로 실행 (ex. 일반적인 프리코스)
    • 2 관리자가 원하는 시점에 실행 (ex. 최종 코딩 테스트)

채점 리포트에 필요한 정보

  • 예시 테스트 케이스 총 N개 중 몇 개 통과했는지 여부
  • 채점 테스트 케이스 총 N개 중 몇 개 통과했는지 여부
  • 지원자는 예시 테스트 케이스 결과만 볼 수 있어야 한다.
  • 관리자는 전체 결과를 볼 수 있어야 한다.

평가 대상 및 평가 방식

  • 기능 요구사항 - 자동 채점
  • 프로그래밍 요구사항, 소감 - 수동 채점

@asebn1
Copy link
Contributor

asebn1 commented Sep 12, 2022

0. 도메인 용어

| 자동채점 == judge

예제 테스트 실행 : 사용자가 요청하는 자동채점(프로그래밍 자동채점)

자동 채점하기 : 관리자 뷰

내부 로직

  • judge(자동 테스트 실행): 자동 테스트 실행 서버로 요청을 보내고 응답을 수신받는 과정
  • reflect judge result(자동 실행 결과 반영) : 자동 실행한 결과를 점수에 반영하는 과정

Test

  • example test (예비, 예제) : 자동 채점 평가 항목에 반영되지 않는, 지원자용 테스트
  • real test (본) : 자동 채점 평가 항목에 반영되는, 관리자용 테스트

testcase(테스트 안에 있는 각각의 테스트들은 테스트케이스라고 부른다.)

1. 자동 채점 기능 흐름(예비 테스트 실행 기준)

  1. 예비 테스트 케이스를 실행한다.
  2. apply 서버에 (실행을) 요청한다.
  3. 요청 시간이 마감 시간 이전인지 검증한다.
  4. DB에서 github id와 pr url 가져온다. (본 채점은 여기부터 시작)
  5. github에서 commit hash를 받아온다.
  6. db를 통해 마지막 채점과 같은 commit hash인지 검증한다.
    • commit hash가 같은 경우, 기존의 결과를 반환한다.
  7. judge 서버에 테스트 실행을 요청하고 요청 정보를 저장한다.
  8. judge 서버에서 보낸 응답을 수신하고 수신 정보를 저장한다.

2. 이슈 구분

1. 예제(example) 테스트 실행 요청을 받아 github API로 필요한 값을 가져온다. 차리랑

  • 예제 테스트 케이스 실행을 요청한다.
  • 요청 시각을 검증한다.
    • 과제 마감 시간 이후에 요청한 경우 예외를 던진다.
  • assignment 테이블 에서 pull request url을 가져온다.
  • github api를 요청한다. https://docs.github.com/en/rest/pulls/pulls#list-commits-on-a-pull-request
  • api 결과(commit list)에서 ‘과제 마감 시간 이전’이면서 동시에 ‘가장 최신’의 commit을 가져온다.
    • 해당 commit이 존재하지 않는 경우 예외를 던진다.
  • 만약 List<Commit>이 max_page(default 30, max 100)와 같은 경우, paging 요청을 진행한다.
    • 검색 조건 찾아보기
  • judge_history 테이블의 commit hash 값을 비교해 중복인지 확인한다.
  • 중복된 commit hash 인 경우 곧바로 데이터를 응답한다.(하단 5번, API 항목 참조)

2. 자동채점 항목을 생성한다. A0


3. 채점 서버에 테스트 실행(real, example)을 요청하고 응답을 수신하여 결과를 저장한다. 차리랑

  • judge_history 테이블의 pull request url, commit hash, judge_item 테이블의 언어 정보 등을 바탕으로 채점 서버(혹은 SQS 등)에 요청을 보낸다.
  • 요청에 대한 응답(request_id)를 수신한다.
  • request_id를 judge_history 테이블에 저장한다.
  • 채점 서버에서 apply server로 request_id와 함께 테스트 실행 결과를 보낸다.
  • 테스트 실행 결과를 judge_history 테이블의 응답 request_id 값을 가진 row를 update한다.

4. 관리자 페이지에서 자동 채점하기(real) 요청 기능을 구현한다. A0

  • 단일 사용자에 대한 자동 채점하기 실행을 요청한다.
    • 관리자 페이지의 평가하기 modal에 자동 채점하기 버튼을 추가한다.
    • missionid와 userId를 통해 단일 자동 채점하기를 요청한다.
    • 요청 시, testStatus, pullRequestUrl, commitUrl, passCount, totalCount, message를 받아온다.
  • 전체 사용자에 대한 자동 채점하기 실행을 요청한다.
    • 관리자 페이지의 선발과정에서 전체 채점하기 버튼을 추가한다.
    • 해당 미션을 수행한 전체 사용자에 대해 자동 채점하기를 요청한다.

5. 실제(real) 테스트 실행 결과를 평가에 반영하고 조회한다. 차리랑

  • judge_history 테이블의 mission_id와 user_id, test_type을 통해 테스트 실행 결과를 조회한다.
  • 실제 테스트 실행 결과를 evaluation_answer의 score에 반영한다.
  • 관리자 페이지에 조회 view를 구현한다.
    • 단건 평가대상자 조회 modal 을 수정한다.(하단 4번 관리자 페이지 피그마 항목 참조)

6. 지원자의 예제(example) 테스트 케이스 실행 결과를 조회한다. A0

  • 예제 테스트케이스 새로고침(조회) API를 추가한다.
    • judge_history 테이블의 mission_id와 user_id을 통해 테스트 실행 결과를 조회한다. (4번이슈)
    • 조회 시 testStatus, pullRequestUrl, commitUrl, passCount, totalCount, message 를 받아온다.
  • 내 지원현황 조회 API를 수정한다.
    • isAutomationjudge(testStatus, pullRequestUrl, commitUrl, passCount, totalCount, message)를 추가로 받아온다.

3. 예상 테이블 스키마

# V3_2__Add_judge_tables.sql

create table judge_item
(
    id                   bigint        not null auto_increment,
    mission_id           bigint        not null,
    evaluation_item_id   bigint,
    test_name            varchar(255),
    programming_language varchar(255),
    primary key (id)
) engine = InnoDB
  default charset = utf8mb4;

create table judge_history
(
    id            bigint       not null auto_increment,
    user_id       bigint       not null,
    mission_id    bigint       not null,
    request_key   char(36)     not null unique,
    commit_hash   char(40)     not null,
    test_type     varchar(255) not null, 
    status_code   int,
    pass_count    int,
    total_count    int,
    primary key (id)
) engine = InnoDB
  default charset = utf8mb4;

create table judge_fail_cause
(
    id             bigint   not null auto_increment,
    request_key    char(36) not null unique,
    message        clob,
    primary key (id)
) engine = InnoDB
  default charset = utf8mb4;

4. 관리자 페이지 피그마

주소: https://www.figma.com/file/2dwEounF9QV2QCRkR5sM3r/%EC%9E%90%EB%8F%99%EC%B1%84%EC%A0%90-%EB%B0%94%EB%94%98-%ED%94%BC%EA%B7%B8%EB%A7%88?node-id=0%3A1

  • 채점 서버 → 채점에 사용할 미션 이름

5. API

1. 내 지원현황 조회

API (/api/recruitments/{recruitmentId}/missions/me)

GET /api/recruitments/{recruitmentId}/missions/me HTTP/1.1
Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXX

as-is

[
    {
        "id": 1,
        "title": "제목",
        "description": "본문",
	"submittable": true,
	"submitted": true,
	"startDateTime": "2022-09-13",
	"endDateTime": "2022-09-13",
	"status": "WAITING"
    },
    {
        "id": 2,
    }
]

to-be

  • submitted가 false인 경우: judgement에 status와 prUrl 외의 내용들이 null
  • commitUrl, passCount, totalCount, message: 없는 경우 null
[
    {
        "id": 1,
        "title": "제목",
        "description": "본문",
	"submittable": false,
	"submitted": true,
	"startDateTime": "2021-10-22 01:00:00",
	"endDateTime": "2021-10-30 02:00:00",
	"status": "제출 종료",
	"isAutomation": true,
	"judgement": {
            "status": "NONE(없음), PENDING(테스트 중), SUCCESS(테스트 성공), FAIL(테스트 실패)",
	    "pullRequestUrl": "https://github.com/woowacourse/jwp-dashboard-http/pull/298",
	    "commitUrl": "https://.../pull/298/commits/6385bfdd2e9a4ae8c41cf7d8b28e79740ad",
	    "passCount": 0,
	    "totalCount": 5,
	    "message": "빌드에 실패했습니다."
        }
    },
    {
        "id": 2
    }
]

2. 예제 테스트 결과 새로고침

요청

GET /api/recruitments/{recruitmentId}/missions/{missionId}/judgement HTTP/1.1
Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXX

응답

"judgement": {
    "status": "NONE(없음), PENDING(테스트 중), SUCCESS(테스트 성공), FAIL(테스트 실패)",
    "pullRequestUrl": "https://github.com/woowacourse/jwp-dashboard-http/pull/298",
    "commitUrl": "https://.../pull/298/commits/6385bfdd2e9a4ae8c41cfffc1f7d8b28e79740ad",
    "passCount": 0,
    "totalCount": 5,
    "message": "빌드에 실패했습니다."
}

3. 실행하기

요청

POST /api/recruitments/{recruitmentId}/missions/{missionId}/judgement HTTP/1.1
Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXX

응답

최초 요청인 경우 or 새로운 commit hash의 요청인경우

"judgement": {
    "status": "NONE(없음), PENDING(테스트 중), SUCCESS(테스트 성공), FAIL(테스트 실패)",
    "pullRequestUrl": "https://github.com/woowacourse/jwp-dashboard-http/pull/298",
    "commitUrl": "https://.../pull/298/commits/6385bfdd2e9a4ae8c41cfffc1f7d8b28e79740ad",
    "passCount": null,
    "totalCount": null,
    "message": null
}
data class RequestBody(
    val testName: String,
    val testType: TestType,
    val pullRequestUrl: String,
    val commitHash: String,
    val programmingLanguage: ProgrammingLanguage 
)

enum class TestType {
    EXAMPLE, REAL
}

enum class ProgrammingLanguage {
    JAVA, JAVASCRIPT, KOTLIN
}

data class ReportPassRequest(
    val requestKey: String,
    val passCount: Int,
    val failCount: Int,
    val totalCount: Int
)

data class ReportFailRequest(
    val requestKey: String,
    val statusCode: StatusCode,
    val message: String?
)

@cjlee38
Copy link
Contributor

cjlee38 commented Sep 15, 2022

image

개략적인 시퀀스 다이어그램 입니다.

@KangYunHo1221
Copy link
Contributor

KangYunHo1221 commented Sep 19, 2022

프론트엔드 이슈 구분

자동채점 기능의 지원자 페이지 UI를 기획한다

자동채점 기능에 대한 Figma

  • 내 지원서를 확인할 수 있다.
  • 지원서와 프리코스를 구분하여 보여준다.
  • 프리코스 제출 상태에 따라 작성하기, 수정하기, 제출완료 버튼을 구현한다.
  • 예제 테스트 실행 버튼을 구현한다.
  • 테스트 중 일 때는 예제 테스트 실행 버튼을 비활성한다.
  • 예제테스트 결과를 텍스트로 보여주고 성공 실패에 따라 색상으로 구분한다.
  • 도움말 버튼을 Hover시에 작동하도록 구현한다.

지원자 페이지의 자동 채점 기능을 구현한다.

  • TypeScript로 구현한다.
  • dummy data를 구현한다.
  • 자동 채점 기능을 구현한다.
  • 지원서 상태에 맞춰 버튼을 구현한다.

자동채점 기능의 mock 과 api 를 추가한다.

  • mocking 을 dummy data 로 구현한다.
  • msw를 이용해 mock을 구현한다.
  • 백엔드 api와 연결하여 기능을 구현한다.

자동채점 기능의 전체 로직을 테스트한다.

  • 기존 테스트 점검을 기준으로 로직을 테스트한다.
  • 자동채점 관련 기능을 테스트 한다.
    • 작성하기 시 예제테스트 실행 버튼이 활성화
    • 예제테스트 실행 시 ,새로고침 활성화, 예제테스트 버튼 비활성화
    • 제출완료시 전체 버튼 비 활성화

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
디자인 Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

6 participants