shinkan-jinkendo/backend/tests/test_planning_exercise_path_qa.py
Lars 87f258be38
All checks were successful
Deploy Development / deploy (push) Successful in 42s
Test Suite / pytest-backend (push) Successful in 43s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 14s
Test Suite / k6 /health Baseline (push) Successful in 34s
Test Suite / playwright-tests (push) Successful in 1m15s
Enhance Path QA with Roadmap-First Features and Gap Detection Improvements
- Introduced `roadmap_qa_mode` to manage QA behavior based on roadmap-first logic, improving gap detection between major steps.
- Updated `detect_path_gaps` to skip gaps for roadmap-planned neighbor pairs, enhancing the accuracy of path assessments.
- Added new helper function `is_roadmap_planned_neighbor_pair` to facilitate roadmap neighbor checks.
- Updated relevant tests to validate new functionality and ensure robustness.
- Incremented application version to 0.8.209 to reflect these changes.
2026-06-09 10:17:30 +02:00

114 lines
3.6 KiB
Python

"""Tests Planungs-KI Phase E/F — Pfad-QA."""
from planning_exercise_path_builder import _pick_best_path_hit
from planning_exercise_semantics import build_semantic_brief
from planning_exercise_path_qa import (
apply_llm_path_reorder,
detect_path_gaps,
is_roadmap_planned_neighbor_pair,
)
def test_pick_best_path_hit_prefers_semantic_score():
brief = build_semantic_brief("Mae Geri Perfektion")
hits = [
{"id": 1, "title": "Mawashi", "score": 0.9, "semantic_score": 0.1},
{"id": 2, "title": "Mae Geri", "score": 0.75, "semantic_score": 0.85},
]
chosen = _pick_best_path_hit(hits, set(), semantic_brief=brief)
assert chosen["id"] == 2
def test_phrase_compact_match_maegeri():
from planning_exercise_semantics import _phrase_in_blob
assert _phrase_in_blob("mae geri", "Erlernen des Mae-Geri aus Einzelbewegungen")
assert _phrase_in_blob("mae geri", "Maegeri Kihon")
def test_pick_best_path_hit_fallback_title_only_in_summary():
from planning_exercise_semantics import pick_best_path_hit
brief = build_semantic_brief("Mae Geri Perfektion")
hits = [
{
"id": 1,
"title": "Kumite Stellungen",
"summary": "",
"score": 0.9,
"semantic_score": 0.02,
},
{
"id": 2,
"title": "Einzelbewegungen",
"summary": "Schrittweise Erlernen des Mae Geri",
"score": 0.5,
"semantic_score": 0.08,
},
]
chosen = pick_best_path_hit(hits, set(), semantic_brief=brief)
assert chosen is not None
assert int(chosen["id"]) == 2
def test_pick_best_path_hit_skips_used():
hits = [{"id": 1, "title": "A", "score": 0.5, "semantic_score": 0.5}]
assert _pick_best_path_hit(hits, {1}) is None
def test_apply_llm_path_reorder_permutation():
steps = [{"exercise_id": 1}, {"exercise_id": 2}, {"exercise_id": 3}]
reordered, applied, notes = apply_llm_path_reorder(
steps,
{"ordered_step_indices": [0, 2, 1], "sequence_notes": ["Vertiefung vor Anwendung"]},
)
assert applied is True
assert [s["exercise_id"] for s in reordered] == [1, 3, 2]
assert notes
def test_is_roadmap_planned_neighbor_pair():
a = {"roadmap_match_source": "stage_spec", "roadmap_major_step_index": 1}
b = {"roadmap_match_source": "stage_spec", "roadmap_major_step_index": 2}
c = {"roadmap_match_source": "stage_spec", "roadmap_major_step_index": 4}
assert is_roadmap_planned_neighbor_pair(a, b) is True
assert is_roadmap_planned_neighbor_pair(a, c) is False
assert is_roadmap_planned_neighbor_pair({"exercise_id": 1}, b) is False
def test_detect_path_gaps_skips_roadmap_neighbors():
brief = build_semantic_brief("Mae Geri")
steps = [
{
"exercise_id": 1,
"title": "A",
"roadmap_match_source": "stage_spec",
"roadmap_major_step_index": 0,
},
{
"exercise_id": 2,
"title": "B",
"roadmap_match_source": "stage_spec",
"roadmap_major_step_index": 1,
},
]
class _FakeCur:
def execute(self, *args, **kwargs):
return None
def fetchall(self):
return []
def fetchone(self):
return {"title": "X", "summary": "", "goal": ""}
gaps = detect_path_gaps(_FakeCur(), steps, brief=brief, roadmap_first=True)
assert gaps == []
def test_apply_llm_path_reorder_invalid_ignored():
steps = [{"exercise_id": 1}, {"exercise_id": 2}]
reordered, applied, _ = apply_llm_path_reorder(steps, {"ordered_step_indices": [0, 0]})
assert applied is False
assert reordered == steps