Skip to content
5 changes: 5 additions & 0 deletions apps/exams/services/admin_exam_deployment_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ def create_deployment(validated_data: dict[str, Any]) -> ExamDeployment:
if not snapshot:
raise DeploymentNoQuestionsError()

for q in snapshot:
answer = q.get("answer", [])
if isinstance(answer, str):
q["answer"] = [answer]

access_code = create_access_code()

deployment = ExamDeployment.objects.create(
Expand Down
121 changes: 121 additions & 0 deletions apps/exams/tests/test_user_exam_submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,124 @@ def test_create_submission_already_exists(self) -> None:

self.assertEqual(response.status_code, status.HTTP_409_CONFLICT)
self.assertEqual(response.data.get("error_detail"), self.error_409)


class TestSnapshotAnswerNormalization(APITestCase):
"""๋ฐฐํฌ ์ƒ์„ฑ ์‹œ ์Šค๋ƒ…์ƒท answer๊ฐ€ ํ•ญ์ƒ ๋ฆฌ์ŠคํŠธ๋กœ ์ €์žฅ๋˜๊ณ , ์ œ์ถœ/์กฐํšŒ ์‹œ ์ •์ƒ ๋™์ž‘ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธ"""

student: User
course: Course
subject: Subject
cohort1: Cohort
cohort2: Cohort
cohort3: Cohort
exam: Exam
question1: ExamQuestion
question2: ExamQuestion

@classmethod
def setUpTestData(cls) -> None:
cls.student = User.objects.create_user(
email="snap_student@test.com",
password="test1234!",
name="์Šค๋ƒ…์ƒทํ…Œ์ŠคํŠธ",
nickname="snapstud",
phone_number="010777777",
is_active=True,
role="STUDENT",
)
cls.course = Course.objects.create(name="์Šค๋ƒ…์ƒทํ…Œ์ŠคํŠธ๊ณผ์ •", tag="WEB")
cls.subject = Subject.objects.create(
course=cls.course,
title="์Šค๋ƒ…์ƒทํ…Œ์ŠคํŠธ๊ณผ๋ชฉ",
number_of_days=30,
number_of_hours=60,
)
cls.cohort1 = Cohort.objects.create(
course=cls.course, number=1, max_student=30, start_date="2024-01-01", end_date="2024-12-31"
)
cls.cohort2 = Cohort.objects.create(
course=cls.course, number=2, max_student=30, start_date="2024-01-01", end_date="2024-12-31"
)
cls.cohort3 = Cohort.objects.create(
course=cls.course, number=3, max_student=30, start_date="2024-01-01", end_date="2024-12-31"
)
cls.exam = Exam.objects.create(subject=cls.subject, title="์Šค๋ƒ…์ƒทํ…Œ์ŠคํŠธ์‹œํ—˜")

# answer๊ฐ€ ๋ฆฌ์ŠคํŠธ์ธ ๋ฌธ์ œ
cls.question1 = ExamQuestion.objects.create(
exam=cls.exam,
question="Django๋Š” Python ์›น ํ”„๋ ˆ์ž„์›Œํฌ์ด๋‹ค",
type="ox",
answer=["O"],
point=10,
explanation="๋งž์Šต๋‹ˆ๋‹ค.",
)
# answer๊ฐ€ ๋ฌธ์ž์—ด์ธ ๋ฌธ์ œ (๊ตฌ๋ฒ„์ „ ๋ฐ์ดํ„ฐ)
cls.question2 = ExamQuestion.objects.create(
exam=cls.exam,
question="Python์€ ์ธํ„ฐํ”„๋ฆฌํ„ฐ ์–ธ์–ด์ด๋‹ค",
type="ox",
answer="O",
point=10,
explanation="๋งž์Šต๋‹ˆ๋‹ค.",
)

def setUp(self) -> None:
self.client = APIClient()
self.client.force_authenticate(user=self.student)
self.submit_url = reverse("user-exam-submission-create")

def _create_deployment(self, cohort: Cohort) -> ExamDeployment:
from apps.exams.services.admin_exam_deployment_service import create_deployment

return create_deployment(
{
"exam_id": self.exam.id,
"cohort_id": cohort.id,
"open_at": "2024-01-01T00:00:00Z",
"close_at": "2024-12-31T23:59:59Z",
"duration_time": 60,
}
)

def _get_submit_data(self, deployment: ExamDeployment) -> dict[str, Any]:
return {
"deployment_id": deployment.id,
"started_at": "2024-01-01T10:00:00Z",
"cheating_count": 0,
"answers": [
{"question_id": self.question1.id, "type": "ox", "submitted_answer": "O"},
{"question_id": self.question2.id, "type": "ox", "submitted_answer": "O"},
],
}

# ๋ฐฐํฌ ์ƒ์„ฑ ์‹œ ์Šค๋ƒ…์ƒท answer๊ฐ€ ํ•ญ์ƒ ๋ฆฌ์ŠคํŠธ๋กœ ์ €์žฅ๋˜๋Š”์ง€ ํ™•์ธ
def test_snapshot_answer_is_always_list(self) -> None:
deployment = self._create_deployment(self.cohort1)

for q in deployment.questions_snapshot_json:
self.assertIsInstance(q["answer"], list)

# ์ œ์ถœ ์‹œ correct_answer_count ์ •์ƒ ๊ณ„์‚ฐ ํ™•์ธ
def test_correct_answer_count_is_correct(self) -> None:
deployment = self._create_deployment(self.cohort2)
response = self.client.post(self.submit_url, self._get_submit_data(deployment), format="json")

self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data["score"], 20)
self.assertEqual(response.data["correct_answer_count"], 2)

# ๊ฒฐ๊ณผ ์กฐํšŒ ์‹œ answer๊ฐ€ ๋ฆฌ์ŠคํŠธ, is_correct ์ •์ƒ ํ‘œ์‹œ ํ™•์ธ
def test_get_submission_answer_is_list_and_is_correct(self) -> None:
deployment = self._create_deployment(self.cohort3)
post_response = self.client.post(self.submit_url, self._get_submit_data(deployment), format="json")
submission_id = post_response.data["submission_id"]

get_response = self.client.get(reverse("user-exam-submission-get", kwargs={"submission_id": submission_id}))

self.assertEqual(get_response.status_code, status.HTTP_200_OK)
self.assertEqual(get_response.data["correct_answer_count"], 2)
for question in get_response.data["questions"]:
self.assertIsInstance(question["answer"], list)
self.assertTrue(question["is_correct"])
Loading