203 lines
6.3 KiB
Python
203 lines
6.3 KiB
Python
|
|
"""
|
|||
|
|
Test script to verify Activity Cluster placeholder registration.
|
|||
|
|
|
|||
|
|
Verifies:
|
|||
|
|
1. All 17 Activity placeholders are registered
|
|||
|
|
2. All have complete metadata (22 mandatory fields)
|
|||
|
|
3. Evidence distribution is correct
|
|||
|
|
"""
|
|||
|
|
import sys
|
|||
|
|
from pathlib import Path
|
|||
|
|
|
|||
|
|
# Add backend to path
|
|||
|
|
sys.path.insert(0, str(Path(__file__).parent / 'backend'))
|
|||
|
|
|
|||
|
|
# Import registrations (triggers auto-registration)
|
|||
|
|
print("Importing placeholder_registry...")
|
|||
|
|
from placeholder_registry import EvidenceType, get_registry
|
|||
|
|
print("Importing activity_metrics...")
|
|||
|
|
try:
|
|||
|
|
from placeholder_registrations import activity_metrics
|
|||
|
|
print("Activity metrics imported successfully")
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"ERROR importing activity_metrics: {e}")
|
|||
|
|
import traceback
|
|||
|
|
traceback.print_exc()
|
|||
|
|
|
|||
|
|
METADATA_REGISTRY = get_registry()
|
|||
|
|
print(f"Registry size after import: {len(METADATA_REGISTRY.get_all())}")
|
|||
|
|
|
|||
|
|
# Expected placeholders
|
|||
|
|
EXPECTED_ACTIVITY_PLACEHOLDERS = [
|
|||
|
|
'activity_summary',
|
|||
|
|
'activity_detail',
|
|||
|
|
'trainingstyp_verteilung',
|
|||
|
|
'training_minutes_week',
|
|||
|
|
'training_frequency_7d',
|
|||
|
|
'quality_sessions_pct',
|
|||
|
|
'ability_balance_strength',
|
|||
|
|
'ability_balance_endurance',
|
|||
|
|
'ability_balance_mental',
|
|||
|
|
'ability_balance_coordination',
|
|||
|
|
'ability_balance_mobility',
|
|||
|
|
'proxy_internal_load_7d',
|
|||
|
|
'monotony_score',
|
|||
|
|
'strain_score',
|
|||
|
|
'rest_day_compliance',
|
|||
|
|
'vo2max_trend_28d',
|
|||
|
|
'activity_score',
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
def test_registration():
|
|||
|
|
"""Test that all Activity placeholders are registered."""
|
|||
|
|
print("=== Activity Cluster Registration Test ===\n")
|
|||
|
|
|
|||
|
|
# Check all expected placeholders
|
|||
|
|
registered = []
|
|||
|
|
missing = []
|
|||
|
|
|
|||
|
|
for key in EXPECTED_ACTIVITY_PLACEHOLDERS:
|
|||
|
|
if METADATA_REGISTRY.get(key) is not None:
|
|||
|
|
registered.append(key)
|
|||
|
|
else:
|
|||
|
|
missing.append(key)
|
|||
|
|
|
|||
|
|
print(f"OK Registered: {len(registered)}/17")
|
|||
|
|
if missing:
|
|||
|
|
print(f"FAIL Missing: {len(missing)}/17")
|
|||
|
|
for key in missing:
|
|||
|
|
print(f" - {key}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
print(f"OK All 17 Activity placeholders registered\n")
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
|
|||
|
|
def test_metadata_completeness():
|
|||
|
|
"""Test that all registered placeholders have complete metadata."""
|
|||
|
|
print("=== Metadata Completeness Test ===\n")
|
|||
|
|
|
|||
|
|
mandatory_fields = [
|
|||
|
|
'key', 'category', 'name_de', 'name_en', 'description_de', 'description_en',
|
|||
|
|
'placeholder_type', 'output_type', 'unit', 'time_window', 'semantic_contract',
|
|||
|
|
'calculation_method', 'source_info', 'data_lineage', 'confidence_logic',
|
|||
|
|
'missing_value_policy', 'known_limitations', 'dependencies',
|
|||
|
|
'layer_2b_reuse_possible', 'example_value'
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
incomplete = []
|
|||
|
|
|
|||
|
|
for key in EXPECTED_ACTIVITY_PLACEHOLDERS:
|
|||
|
|
metadata = METADATA_REGISTRY.get(key)
|
|||
|
|
if metadata is None:
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
missing_fields = []
|
|||
|
|
|
|||
|
|
for field in mandatory_fields:
|
|||
|
|
value = getattr(metadata, field, None)
|
|||
|
|
if value is None or value == '' or value == []:
|
|||
|
|
missing_fields.append(field)
|
|||
|
|
|
|||
|
|
if missing_fields:
|
|||
|
|
incomplete.append((key, missing_fields))
|
|||
|
|
|
|||
|
|
if incomplete:
|
|||
|
|
print(f"FAIL Incomplete metadata: {len(incomplete)}/17")
|
|||
|
|
for key, fields in incomplete:
|
|||
|
|
print(f" - {key}: missing {fields}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
print(f"OK All 17 placeholders have complete metadata (20 mandatory fields)\n")
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
|
|||
|
|
def test_evidence_distribution():
|
|||
|
|
"""Test evidence tagging distribution."""
|
|||
|
|
print("=== Evidence Distribution Test ===\n")
|
|||
|
|
|
|||
|
|
evidence_counts = {
|
|||
|
|
EvidenceType.CODE_DERIVED: 0,
|
|||
|
|
EvidenceType.DRAFT_DERIVED: 0,
|
|||
|
|
EvidenceType.MIXED: 0,
|
|||
|
|
EvidenceType.TO_VERIFY: 0,
|
|||
|
|
EvidenceType.UNRESOLVED: 0,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
total_tags = 0
|
|||
|
|
|
|||
|
|
for key in EXPECTED_ACTIVITY_PLACEHOLDERS:
|
|||
|
|
metadata = METADATA_REGISTRY.get(key)
|
|||
|
|
if metadata is None:
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
# Count evidence tags (22 fields)
|
|||
|
|
for field in metadata.get_all_evidence_fields():
|
|||
|
|
evidence = metadata.get_evidence(field)
|
|||
|
|
if evidence:
|
|||
|
|
evidence_counts[evidence] = evidence_counts.get(evidence, 0) + 1
|
|||
|
|
total_tags += 1
|
|||
|
|
|
|||
|
|
print(f"Total evidence tags: {total_tags} (expected ~374 = 17 × 22)")
|
|||
|
|
print("\nDistribution:")
|
|||
|
|
for evidence_type, count in evidence_counts.items():
|
|||
|
|
percentage = (count / total_tags * 100) if total_tags > 0 else 0
|
|||
|
|
print(f" {evidence_type.value:15s}: {count:3d} ({percentage:5.1f}%)")
|
|||
|
|
|
|||
|
|
print("\nExpected distribution:")
|
|||
|
|
print(" CODE_DERIVED: ~60% (directly from code)")
|
|||
|
|
print(" DRAFT_DERIVED: ~15% (from canonical draft)")
|
|||
|
|
print(" MIXED: ~15% (combined sources)")
|
|||
|
|
print(" TO_VERIFY: ~10% (needs verification)")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
|
|||
|
|
def dump_sample_placeholder():
|
|||
|
|
"""Dump one complete placeholder as sample."""
|
|||
|
|
print("=== Sample Placeholder: activity_score ===\n")
|
|||
|
|
|
|||
|
|
metadata = METADATA_REGISTRY.get('activity_score')
|
|||
|
|
if metadata is None:
|
|||
|
|
print("FAIL activity_score not found in registry")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
print(f"Key: {metadata.key}")
|
|||
|
|
print(f"Category: {metadata.category}")
|
|||
|
|
print(f"Name (DE): {metadata.name_de}")
|
|||
|
|
print(f"Name (EN): {metadata.name_en}")
|
|||
|
|
print(f"Type: {metadata.placeholder_type.value}")
|
|||
|
|
print(f"Output: {metadata.output_type.value}")
|
|||
|
|
print(f"Unit: {metadata.unit}")
|
|||
|
|
print(f"Time Window: {metadata.time_window}")
|
|||
|
|
print(f"\nDescription (DE):")
|
|||
|
|
print(f" {metadata.description_de[:100]}...")
|
|||
|
|
print(f"\nSemantic Contract:")
|
|||
|
|
print(f" {metadata.semantic_contract[:100]}...")
|
|||
|
|
print(f"\nCalculation Method:")
|
|||
|
|
print(f" {metadata.calculation_method[:100]}...")
|
|||
|
|
print(f"\nKnown Limitations:")
|
|||
|
|
print(f" {metadata.known_limitations[:150]}...")
|
|||
|
|
print(f"\nDependencies: {len(metadata.dependencies)} items")
|
|||
|
|
print(f"Layer 2b Reuse: {metadata.layer_2b_reuse_possible}")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == '__main__':
|
|||
|
|
success = True
|
|||
|
|
|
|||
|
|
success &= test_registration()
|
|||
|
|
success &= test_metadata_completeness()
|
|||
|
|
success &= test_evidence_distribution()
|
|||
|
|
success &= dump_sample_placeholder()
|
|||
|
|
|
|||
|
|
if success:
|
|||
|
|
print("OK All tests passed - Activity Cluster registration is complete and valid")
|
|||
|
|
sys.exit(0)
|
|||
|
|
else:
|
|||
|
|
print("FAIL Some tests failed - see output above")
|
|||
|
|
sys.exit(1)
|