11import re
22from pathlib import Path
33
4+ from app import extended_curriculum
45from app .content import EXAMS , LESSONS , MODULES , QUESTION_BY_ID
5- from app .evaluator import evaluate
6- from app .extended_curriculum import EXTRA_LESSONS
6+ from app .evaluator import evaluate , normalize
7+ from app .extended_curriculum import EXTRA_LESSONS , build_extended_course
78from app .lessons_13_25 import LESSONS_13_25
89
910LESSONS_13_25_IDENTITY = [
@@ -114,13 +115,14 @@ def test_lessons_four_to_six_do_not_require_future_topics() -> None:
114115
115116def test_extended_questions_are_fair_and_exams_are_mixed () -> None :
116117 extended_lessons = [lesson for lesson in LESSONS if lesson ["order" ] >= 13 ]
117- choice_positions = {
118+ choice_positions = [
118119 question ["options" ].index (question ["answer" ])
119120 for lesson in extended_lessons
120121 for question in lesson ["questions" ]
121122 if question ["kind" ] == "choice"
122- }
123- assert len (choice_positions ) > 1
123+ ]
124+ assert len (set (choice_positions )) > 1
125+ assert all (0 <= position < 3 for position in choice_positions )
124126 assert (
125127 sum (
126128 len (question ["answers" ]) > 1
@@ -132,6 +134,52 @@ def test_extended_questions_are_fair_and_exams_are_mixed() -> None:
132134 )
133135 extended_modules = {lesson ["module_id" ] for lesson in extended_lessons }
134136 for module_id in extended_modules :
135- assert {
136- QUESTION_BY_ID [question_id ]["kind" ] for question_id in EXAMS [module_id ]["question_ids" ]
137- } == {"choice" , "input" , "code" }
137+ question_ids = EXAMS [module_id ]["question_ids" ]
138+ assert len (question_ids ) == len (set (question_ids )) == 4
139+ assert {QUESTION_BY_ID [question_id ]["kind" ] for question_id in question_ids } == {
140+ "choice" ,
141+ "input" ,
142+ "code" ,
143+ }
144+
145+ term_question = next (
146+ question
147+ for lesson in extended_lessons
148+ for question in lesson ["questions" ]
149+ if question ["kind" ] == "input" and len (question ["answers" ]) > 1
150+ )
151+ assert all (
152+ normalize (answer ) not in normalize (term_question ["placeholder" ])
153+ for answer in term_question ["answers" ]
154+ )
155+
156+ keyword , synonyms = "sorted" , ("сортировка" ,)
157+ answers = next (
158+ question ["answers" ]
159+ for lesson in extended_lessons
160+ for question in lesson ["questions" ]
161+ if question ["kind" ] == "input" and keyword in question ["answers" ]
162+ )
163+ assert normalize (f" { synonyms [0 ].upper ()} " ) in {normalize (answer ) for answer in answers }
164+
165+
166+ def test_extended_generation_is_deterministic_and_handles_short_modules (monkeypatch ) -> None :
167+ first = build_extended_course ()
168+ second = build_extended_course ()
169+ assert first == second
170+
171+ monkeypatch .setattr (
172+ extended_curriculum ,
173+ "COURSE_UNITS" ,
174+ [
175+ {
176+ ** extended_curriculum .COURSE_UNITS [0 ],
177+ "lessons" : extended_curriculum .COURSE_UNITS [0 ]["lessons" ][:1 ],
178+ }
179+ ],
180+ )
181+ monkeypatch .setattr (
182+ extended_curriculum , "TASK_CYCLES" , [extended_curriculum .TASK_CYCLES [0 ][:1 ]]
183+ )
184+ _ , _ , exams = build_extended_course ()
185+ assert len (next (iter (exams .values ()))["question_ids" ]) == 3
0 commit comments