- Implemented a new test script `test_activity_registration.py` to verify the registration of Activity placeholders, ensuring all expected placeholders are registered, have complete metadata, and correct evidence distribution. - Created a new smoke test suite `dev-smoke-test.spec.js` to validate the login process, dashboard loading, and navigation to key sections, while checking for critical console errors. - Added a JSON file `test-results.last-run.json` to track the status of the last test run, indicating failures if any tests do not pass.
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)
|