shinkan-jinkendo/backend/tests/test_skill_scoring.py
Lars 9a0cf7f823
All checks were successful
Deploy Development / deploy (push) Successful in 43s
Test Suite / pytest-backend (push) Successful in 42s
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 1m15s
Enhance Skill Scoring and Profile Functionality
- Introduced a new function to calculate club-specific skill percentages, ensuring values are capped at 100%.
- Updated skill profile calculations to include indicators for the best club performance per skill.
- Enhanced frontend components to display club best indicators and improved layout for skill profiles.
- Refactored CSS styles for skill profile components, ensuring a more cohesive and user-friendly interface.
- Updated tests to validate new functionality and ensure accurate representation of skill metrics.
2026-05-21 09:33:20 +02:00

126 lines
4.2 KiB
Python

"""Unit-Tests für gewichtetes Fähigkeiten-Scoring (Phase 3)."""
from skill_scoring import (
ExerciseOccurrence,
compute_skill_profile,
match_score_for_skill_ids,
_club_universal_percent,
_level_range_multiplier,
_skill_link_multiplier,
)
def test_skill_link_multiplier_intensity_and_levels():
assert _skill_link_multiplier(intensity="hoch") == 1.2
assert _skill_link_multiplier(intensity="niedrig") == 0.85
wide = _skill_link_multiplier(
intensity="mittel",
required_level="basis",
target_level="optimierung",
)
narrow = _skill_link_multiplier(
intensity="mittel",
required_level="grundlagen",
target_level="grundlagen",
)
assert wide > narrow
def test_level_range_multiplier_span():
assert _level_range_multiplier(None, None) == 1.0
assert _level_range_multiplier("aufbau", "fortgeschritten") > _level_range_multiplier("basis", "basis")
def test_compute_skill_profile_aggregates_weights():
occurrences = [
ExerciseOccurrence(exercise_id=1, planned_duration_min=60),
ExerciseOccurrence(exercise_id=1, planned_duration_min=30),
]
skills_map = {
1: [
{
"skill_id": 10,
"skill_name": "Distanz",
"category": "kihon",
"category_id": 1,
"category_name": "kihon",
"main_category_id": 100,
"main_category_name": "Technik",
"intensity": "hoch",
"required_level": "grundlagen",
"target_level": "aufbau",
"exercise_title": "Übung A",
},
{
"skill_id": 11,
"skill_name": "Balance",
"category": "kihon",
"category_id": 1,
"category_name": "kihon",
"main_category_id": 100,
"main_category_name": "Technik",
"intensity": "niedrig",
"required_level": "basis",
"target_level": "basis",
"exercise_title": "Übung A",
},
],
}
profile = compute_skill_profile(occurrences, skills_map)
assert profile["scoring_version"] == "1.2"
assert profile["exercise_occurrence_count"] == 2
assert profile["distinct_exercise_count"] == 1
assert len(profile["skills"]) == 2
assert profile["skills"][0]["skill_id"] == 10
assert profile["total_weight"] > profile["skills"][1]["weight"]
assert abs(sum(s["share_percent"] for s in profile["skills"]) - 100.0) < 0.1
assert len(profile["by_main_category"]) == 1
assert profile["by_main_category"][0]["categories"][0]["top_skill"]["skill_id"] == 10
def test_universal_percent_against_corpus_max():
occurrences = [ExerciseOccurrence(exercise_id=1, planned_duration_min=50)]
skills_map = {
1: [
{
"skill_id": 10,
"skill_name": "Koordination",
"category_name": "Koordination",
"category_id": 2,
"main_category_id": 200,
"main_category_name": "Körper",
},
],
}
profile = compute_skill_profile(
occurrences,
skills_map,
reference_max_by_skill={10: 100.0},
)
assert profile["has_reference_scale"] is True
assert profile["skills"][0]["universal_percent"] == 50.0
assert profile["skills"][0]["is_club_best_for_skill"] is False
def test_club_universal_percent_capped_at_100():
pct, is_best = _club_universal_percent(150.0, 100.0)
assert pct == 100.0
assert is_best is True
pct2, _ = _club_universal_percent(72.6, 100.0)
assert pct2 == 72.6
def test_match_score_for_skill_ids():
profile = {
"total_weight": 100.0,
"skills": [
{"skill_id": 1, "skill_name": "A", "weight": 40.0},
{"skill_id": 2, "skill_name": "B", "weight": 60.0},
],
}
m = match_score_for_skill_ids(profile, [1])
assert m["match_weight"] == 40.0
assert m["match_score"] == 40.0
assert m["match_percent"] == 40.0
assert m["artifact_focus_percent"] == 40.0
assert m["matched_skill_ids"] == [1]