Skip to content

Commit 3e73829

Browse files
committed
Added tests for matchedCase scenarios in evaluate workflow, including handling of case matching, feedback, and mark overrides.
1 parent 30c583c commit 3e73829

2 files changed

Lines changed: 154 additions & 0 deletions

File tree

tests/mued_handling_test.py

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,5 +401,158 @@ def test_preview_result_propagated(self):
401401
self.assertEqual(response[0]["preSubmissionFeedback"]["sympy"], "x+1") # type: ignore
402402

403403

404+
class TestMuEdMatchedCase(unittest.TestCase):
405+
def setUp(self) -> None:
406+
os.environ["SCHEMA_DIR"] = _SCHEMAS_DIR
407+
commands.evaluation_function = lambda response, answer, params: {
408+
"is_correct": response == answer,
409+
"feedback": "Default feedback.",
410+
}
411+
return super().setUp()
412+
413+
def tearDown(self) -> None:
414+
os.environ.pop("SCHEMA_DIR", None)
415+
commands.evaluation_function = None
416+
return super().tearDown()
417+
418+
def test_matched_case_is_none_when_no_cases(self):
419+
event = {
420+
"path": "/evaluate",
421+
"body": {
422+
"submission": {"type": "MATH", "content": {"expression": "x+1"}},
423+
"task": {"title": "T", "referenceSolution": {"expression": "x+2"}},
424+
},
425+
}
426+
427+
response = handler(event)
428+
429+
self.assertIsNone(response[0]["matchedCase"]) # type: ignore
430+
431+
def test_matched_case_is_none_when_no_case_matches(self):
432+
event = {
433+
"path": "/evaluate",
434+
"body": {
435+
"submission": {"type": "MATH", "content": {"expression": "x+1"}},
436+
"task": {"title": "T", "referenceSolution": {"expression": "x+2"}},
437+
"configuration": {
438+
"params": {
439+
"cases": [
440+
{"answer": "x+3", "feedback": "Try again."},
441+
]
442+
}
443+
},
444+
},
445+
}
446+
447+
response = handler(event)
448+
449+
self.assertIsNone(response[0]["matchedCase"]) # type: ignore
450+
451+
def test_matched_case_index_when_first_case_matches(self):
452+
event = {
453+
"path": "/evaluate",
454+
"body": {
455+
"submission": {"type": "MATH", "content": {"expression": "100+100.1(j)"}},
456+
"task": {
457+
"title": "Evaluation Task",
458+
"referenceSolution": {"expression": "100+100.1j"},
459+
},
460+
"configuration": {
461+
"params": {
462+
"atol": 0,
463+
"rtol": 0,
464+
"strict_syntax": False,
465+
"physical_quantity": False,
466+
"elementary_functions": True,
467+
"cases": [
468+
{
469+
"answer": "100+100.1(j)",
470+
"params": {
471+
"atol": 0,
472+
"rtol": 0,
473+
"strict_syntax": False,
474+
"physical_quantity": False,
475+
"elementary_functions": True,
476+
},
477+
"feedback": "Hello",
478+
}
479+
],
480+
}
481+
},
482+
},
483+
}
484+
485+
response = handler(event)
486+
487+
self.assertEqual(response[0]["matchedCase"], 0) # type: ignore
488+
self.assertEqual(response[0]["message"], "Hello") # type: ignore
489+
490+
def test_matched_case_index_second_case(self):
491+
event = {
492+
"path": "/evaluate",
493+
"body": {
494+
"submission": {"type": "MATH", "content": {"expression": "x+1"}},
495+
"task": {"title": "T", "referenceSolution": {"expression": "x+2"}},
496+
"configuration": {
497+
"params": {
498+
"cases": [
499+
{"answer": "x+3", "feedback": "Not case 0."},
500+
{"answer": "x+1", "feedback": "This is case 1."},
501+
{"answer": "x+4", "feedback": "Not case 2."},
502+
]
503+
}
504+
},
505+
},
506+
}
507+
508+
response = handler(event)
509+
510+
self.assertEqual(response[0]["matchedCase"], 1) # type: ignore
511+
self.assertEqual(response[0]["message"], "This is case 1.") # type: ignore
512+
513+
def test_matched_case_is_none_when_correct(self):
514+
event = {
515+
"path": "/evaluate",
516+
"body": {
517+
"submission": {"type": "MATH", "content": {"expression": "x+1"}},
518+
"task": {"title": "T", "referenceSolution": {"expression": "x+1"}},
519+
"configuration": {
520+
"params": {
521+
"cases": [
522+
{"answer": "x+1", "feedback": "Matched but not checked."},
523+
]
524+
}
525+
},
526+
},
527+
}
528+
529+
response = handler(event)
530+
531+
self.assertEqual(response[0]["awardedPoints"], 1) # type: ignore
532+
self.assertIsNone(response[0]["matchedCase"]) # type: ignore
533+
534+
def test_matched_case_with_mark_override(self):
535+
event = {
536+
"path": "/evaluate",
537+
"body": {
538+
"submission": {"type": "MATH", "content": {"expression": "x+1"}},
539+
"task": {"title": "T", "referenceSolution": {"expression": "x+2"}},
540+
"configuration": {
541+
"params": {
542+
"cases": [
543+
{"answer": "x+1", "feedback": "Close enough!", "mark": 1},
544+
]
545+
}
546+
},
547+
},
548+
}
549+
550+
response = handler(event)
551+
552+
self.assertEqual(response[0]["matchedCase"], 0) # type: ignore
553+
self.assertEqual(response[0]["awardedPoints"], 1) # type: ignore
554+
self.assertEqual(response[0]["message"], "Close enough!") # type: ignore
555+
556+
404557
if __name__ == "__main__":
405558
unittest.main()

tools/commands.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ def _run_muEd_evaluation(body: JsonType) -> List[Dict]:
173173
feedback_item: Dict = {
174174
"message": feedback_text if isinstance(feedback_text, str) else str(feedback_text),
175175
"awardedPoints": int(is_correct),
176+
"matchedCase": result.get("matched_case"),
176177
}
177178

178179
if result.get("tags"):

0 commit comments

Comments
 (0)