All checks were successful
Deploy Development / deploy (push) Successful in 42s
Test Suite / pytest-backend (push) Successful in 48s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m22s
- Updated `build_gap_fill_goal_text` to include expected skills in the generated text, improving clarity for users. - Enhanced `_roadmap_gap_snapshot_for_spec` to incorporate skill expectations from the progression stage, enriching the roadmap context. - Modified `_annotate_roadmap_step` to append skill expectations to the step reasons, providing additional insights. - Updated tests to verify the inclusion of expected skills in the gap fill goal text. - Incremented application version to 0.8.215 to reflect these changes.
122 lines
4.0 KiB
Python
122 lines
4.0 KiB
Python
"""Tests wiederverwendbare Fähigkeiten-Erwartungen (Progressionsgraph + später Planung)."""
|
|
from unittest.mock import MagicMock
|
|
|
|
from planning_skill_expectations import (
|
|
SCOPE_PROGRESSION_PATH,
|
|
SCOPE_PROGRESSION_STAGE,
|
|
PlanningSkillExpectationInput,
|
|
apply_expectations_to_target,
|
|
build_planning_skill_expectations,
|
|
expectation_input_from_progression_path,
|
|
expectation_input_from_progression_stage,
|
|
)
|
|
|
|
|
|
class _FakeCursor:
|
|
def __init__(self, skills):
|
|
self._skills = skills
|
|
|
|
def execute(self, query, params=None):
|
|
del query
|
|
if params and len(params) >= 2:
|
|
needle = str(params[0]).strip("%").lower()
|
|
exact = str(params[1]).lower()
|
|
matches = [
|
|
s
|
|
for s in self._skills
|
|
if needle in s["name"].lower() or s["name"].lower() == exact
|
|
]
|
|
self._row = matches[0] if matches else None
|
|
else:
|
|
self._row = None
|
|
|
|
def fetchone(self):
|
|
return self._row
|
|
|
|
|
|
def _fake_skill_rows():
|
|
return [
|
|
(1, "Koordination", 0),
|
|
(2, "Timing", 0),
|
|
(3, "Distanz", 0),
|
|
(4, "Kime", 0),
|
|
]
|
|
|
|
|
|
def test_expectation_input_from_progression_stage_merges_sources(monkeypatch):
|
|
monkeypatch.setattr(
|
|
"planning_skill_expectations._load_skills_for_text_match",
|
|
lambda cur: _fake_skill_rows(),
|
|
)
|
|
inp = expectation_input_from_progression_stage(
|
|
goal_query="Kumite Beinarbeit",
|
|
goal_analysis={
|
|
"primary_topic": "Kumite",
|
|
"start_assumption": "gleichförmige Steppbewegung",
|
|
"target_state": "explosiver Angriff",
|
|
},
|
|
resolved_structured={"roadmap_notes": "Kindergruppe"},
|
|
stage_spec={
|
|
"learning_goal": "variable Rhythmen",
|
|
"load_profile": ["timing", "distanz"],
|
|
"phase": "vertiefung",
|
|
},
|
|
semantic_brief_summary={"must_phrases": ["Beinarbeit"], "primary_topic": "Kumite"},
|
|
major_step={"phase": "vertiefung", "learning_goal": "Major-Ziel"},
|
|
)
|
|
assert inp.scope == SCOPE_PROGRESSION_STAGE
|
|
assert inp.primary_topic == "Kumite"
|
|
assert inp.start_situation == "gleichförmige Steppbewegung"
|
|
assert inp.load_profile == ["timing", "distanz"]
|
|
assert "Beinarbeit" in inp.skill_hints
|
|
|
|
|
|
def test_build_planning_skill_expectations_load_profile_and_text(monkeypatch):
|
|
monkeypatch.setattr(
|
|
"planning_skill_expectations._load_skills_for_text_match",
|
|
lambda cur: _fake_skill_rows(),
|
|
)
|
|
cur = _FakeCursor(
|
|
[
|
|
{"id": 2, "name": "Timing"},
|
|
{"id": 3, "name": "Distanz"},
|
|
]
|
|
)
|
|
inp = PlanningSkillExpectationInput(
|
|
scope=SCOPE_PROGRESSION_STAGE,
|
|
primary_topic="Kumite",
|
|
goal_query="Kumite Beinarbeit mit Timing",
|
|
load_profile=["timing", "distanz"],
|
|
)
|
|
exp = build_planning_skill_expectations(cur, inp)
|
|
assert exp.scope == SCOPE_PROGRESSION_STAGE
|
|
assert "load_profile" in exp.sources or "text_match" in exp.sources
|
|
names = {it.skill_name for it in exp.items}
|
|
assert "Timing" in names or "Distanz" in names
|
|
assert exp.skill_weights
|
|
|
|
|
|
def test_expectation_input_from_progression_path_scope():
|
|
inp = expectation_input_from_progression_path(
|
|
goal_query="Mae Geri Perfektion",
|
|
goal_analysis={"primary_topic": "Mae Geri"},
|
|
resolved_structured={"start_situation": "Grundstellung", "target_state": "freier Kick"},
|
|
)
|
|
assert inp.scope == SCOPE_PROGRESSION_PATH
|
|
assert inp.start_situation == "Grundstellung"
|
|
assert inp.target_state == "freier Kick"
|
|
|
|
|
|
def test_apply_expectations_to_target_noop_without_weights():
|
|
class _Target:
|
|
skill_weights = {}
|
|
|
|
def to_summary_dict(self, cur):
|
|
return {}
|
|
|
|
target = _Target()
|
|
from planning_skill_expectations import PlanningSkillExpectations
|
|
|
|
empty = PlanningSkillExpectations(scope=SCOPE_PROGRESSION_STAGE, skill_weights={}, items=[], sources=[])
|
|
assert apply_expectations_to_target(target, empty) is target
|