import asyncio from app.schemas.cross_validation import AnswerKind, TaskType from app.schemas.numeric import NumericCheckItem from app.services.numeric_router import run_numeric_checks_with_router class FakeContext: def model_dump(self, mode="json"): return {"statement": "Résoudre 3x - 9 = 0."} class FakeCandidate: def __init__(self, task_type, answer_kind): self.task_type = task_type self.expected_answer_kind = answer_kind async def fake_translate_equation(**kwargs): return FakeCandidate(TaskType.EQUATION, AnswerKind.SOLUTION_SET) async def fake_translate_derivative(**kwargs): return FakeCandidate(TaskType.DERIVATIVE, AnswerKind.EXPRESSION) async def fake_solution_set_runner(**kwargs): return NumericCheckItem( check_type="equivalence", expression="3", expected="x = 3", is_valid=True, details="student_llm_and_wolfram_are_consistent", wolfram_status="ok", cas_status="WOLFRAM_ONLY", preferred_engine="wolfram", confidence_impact="increase", ) def test_numeric_router_routes_equation_solution_set(monkeypatch): import app.services.numeric_router as router monkeypatch.setattr(router, "translate_exercise_to_wolfram_with_llm", fake_translate_equation) monkeypatch.setattr(router, "run_solution_set_cross_validation_numeric_check", fake_solution_set_runner) report = asyncio.run(run_numeric_checks_with_router(answer_text="S = {3}", pedagogical_context=FakeContext())) assert len(report.checks) == 1 assert report.checks[0].wolfram_status == "ok" assert report.checks[0].is_valid is True assert report.needs_human_review is False def test_numeric_router_skips_derivative(monkeypatch): import app.services.numeric_router as router monkeypatch.setattr(router, "translate_exercise_to_wolfram_with_llm", fake_translate_derivative) report = asyncio.run(run_numeric_checks_with_router(answer_text="S = {3}", pedagogical_context=FakeContext())) assert len(report.checks) == 1 assert report.checks[0].wolfram_status == "skipped" assert report.checks[0].cas_status == "NO_CAS_VALIDATION" assert report.checks[0].is_valid is True assert "numeric_router_skipped_unsupported_task=derivative" in report.checks[0].details assert report.needs_human_review is False