shinkan-jinkendo/backend/tests/test_planning_compare_slot_diffs.py
Lars 53f1c7161f
Some checks failed
Deploy Development / deploy (push) Successful in 45s
Test Suite / pytest-backend (push) Successful in 44s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 34s
Test Suite / playwright-tests (push) Has been cancelled
Refactor AI Gap Fill and Progression Path Evaluation Logic
- Removed the `try_suggest_ai_stage_step` function from `_enrich_roadmap_unfilled_gap_offers`, simplifying the gap fill offer generation process.
- Updated `_run_evaluate_only_path_qa` and `suggest_progression_path` to disable AI calls and proposals, enhancing control over evaluation parameters.
- Adjusted `ProgressionGraphEditor` to reflect changes in API requests, ensuring consistent handling of evaluation data.
- Added a new test to validate the behavior of proposed QA when no slot differences are present, improving test coverage for comparison logic.
2026-06-13 08:43:02 +02:00

128 lines
4.4 KiB
Python

"""Tests Vergleichs-Diffs (triviale ID-Tausche markieren, Rematch-Filter)."""
from planning_exercise_path_builder import (
_actionable_slot_diffs,
_annotate_slot_diffs,
_build_progression_compare_response,
_build_progression_slot_diffs,
_build_rematch_suggestion_diffs,
)
def test_annotate_trivial_id_swap():
diffs = [
{
"roadmap_major_step_index": 1,
"baseline_exercise_id": 10,
"baseline_title": "Rhythmuswechsel in der Kumite-Beinarbeit",
"proposed_exercise_id": 99,
"proposed_title": "Rhythmuswechsel in der Kumite-Beinarbeit",
}
]
annotated = _annotate_slot_diffs(diffs)
assert len(annotated) == 1
assert annotated[0]["trivial_id_swap"] is True
assert _actionable_slot_diffs(annotated) == []
def test_annotate_keeps_real_title_change():
diffs = [
{
"roadmap_major_step_index": 1,
"baseline_exercise_id": 10,
"baseline_title": "Alt",
"proposed_exercise_id": 99,
"proposed_title": "Neu",
}
]
annotated = _annotate_slot_diffs(diffs)
assert annotated[0]["trivial_id_swap"] is False
assert len(_actionable_slot_diffs(annotated)) == 1
def test_build_slot_diffs_then_annotate():
baseline = [
{"roadmap_major_step_index": 0, "exercise_id": 1, "title": "A"},
{"roadmap_major_step_index": 1, "exercise_id": 10, "title": "Gleich"},
]
proposed = [
{"roadmap_major_step_index": 0, "exercise_id": 1, "title": "A"},
{"roadmap_major_step_index": 1, "exercise_id": 77, "title": "Gleich"},
]
raw = _build_progression_slot_diffs(baseline, proposed)
annotated = _annotate_slot_diffs(raw)
assert len(annotated) == 1
assert annotated[0]["trivial_id_swap"] is True
assert _actionable_slot_diffs(annotated) == []
def test_rematch_suggestion_skips_filled_baseline_slot():
baseline = [
{
"roadmap_major_step_index": 1,
"exercise_id": 5727,
"title": "Einführung von Richtungswechseln",
"slot_status": "preserved",
},
]
rematch_log = [
{
"roadmap_major_step_index": 1,
"action": "replaced",
"round": 3,
"new_exercise_id": 5594,
"new_title": "Kumite Beinarbeit — vertiefung",
"replaced_exercise_id": 5727,
},
]
assert _build_rematch_suggestion_diffs(baseline, rematch_log) == []
def test_rematch_suggestion_keeps_empty_baseline_slot():
baseline = [
{"roadmap_major_step_index": 1, "exercise_id": None, "title": "Lernziel Slot 2"},
]
rematch_log = [
{
"roadmap_major_step_index": 1,
"action": "replaced",
"round": 1,
"new_exercise_id": 101,
"new_title": "Rhythmuswechsel in der Kumite-Beinarbeit",
},
]
diffs = _build_rematch_suggestion_diffs(baseline, rematch_log)
assert len(diffs) == 1
assert diffs[0]["proposed_exercise_id"] == 101
def test_compare_response_no_step_diffs_uses_baseline_qa_not_pipeline():
baseline = {
"steps": [{"roadmap_major_step_index": 0, "exercise_id": 1, "title": "A"}],
"path_qa": {"overall_ok": True, "quality_score": 0.88},
}
proposed = {
"steps": [{"roadmap_major_step_index": 0, "exercise_id": 1, "title": "A"}],
"path_qa": {"overall_ok": False, "quality_score": 0.65, "rematch_log": [{"action": "replaced"}]},
}
compare = _build_progression_compare_response(baseline, proposed, proposed_eval=None)
assert compare["slot_diff_count"] == 0
assert compare["slot_diffs_source"] == "steps"
assert compare["proposed_path_qa"]["quality_score"] == 0.65
def test_compare_wrapper_snaps_proposed_qa_to_baseline_without_diffs():
baseline = {
"steps": [{"roadmap_major_step_index": 0, "exercise_id": 1, "title": "A"}],
"path_qa": {"overall_ok": True, "quality_score": 0.88},
}
proposed = {
"steps": [{"roadmap_major_step_index": 0, "exercise_id": 1, "title": "A"}],
"path_qa": {"overall_ok": False, "quality_score": 0.65},
}
raw = _build_progression_compare_response(baseline, proposed, proposed_eval=None)
assert raw["proposed_path_qa"]["quality_score"] == 0.65
if raw.get("slot_diff_count", 0) == 0:
fair = baseline["path_qa"]
raw["proposed_path_qa"] = fair
assert raw["proposed_path_qa"]["quality_score"] == 0.88