Files

185 lines
6.8 KiB
Python

"""
Simple test runner for pattern validation (bypasses pytest collection issues)
"""
import sys
from pathlib import Path
# Add parent directory to path
sys.path.insert(0, str(Path(__file__).parent.parent))
# Import test functions
from tests.test_pattern_validation import (
load_all_pattern_files,
load_pattern_file,
extract_error_keys_from_i18n,
extract_suggestions_from_i18n,
SUPPORTED_LANGUAGES,
VALID_CATEGORIES,
PROJECT_ROOT
)
import re
def run_tests():
"""Run all validation tests"""
print("="*70)
print("Pattern Validation Test Suite")
print("="*70)
# Load data
print("\nINFO: Loading pattern files...")
pattern_files = load_all_pattern_files()
print(f" Found {len(pattern_files)} pattern files")
all_patterns = []
for file_path in pattern_files:
data = load_pattern_file(file_path)
for pattern in data.get("patterns", []):
pattern["_source_file"] = str(file_path.relative_to(PROJECT_ROOT))
all_patterns.append(pattern)
print(f" Loaded {len(all_patterns)} patterns total")
print("\nINFO: Loading i18n data...")
error_keys = extract_error_keys_from_i18n()
suggestions = extract_suggestions_from_i18n()
print(f" Found {len(error_keys)} error keys")
print(f" Found translations for {len(suggestions)} languages")
# Test 1: JSON validity
print("\nOK Test 1: JSON Validity")
for file_path in pattern_files:
try:
load_pattern_file(file_path)
print(f" PASS {file_path.name}")
except Exception as e:
print(f" FAIL {file_path.name}: {e}")
return False
# Test 2: Required fields
print("\nOK Test 2: Required Fields")
required_fields = ["id", "regex", "error_key", "priority", "category"]
for pattern in all_patterns:
for field in required_fields:
if field not in pattern:
print(f" FAIL Pattern {pattern.get('id', 'UNKNOWN')} missing field: {field}")
return False
print(f" PASS All {len(all_patterns)} patterns have required fields")
# Test 3: Regex compilation
print("\nOK Test 3: Regex Compilation")
for pattern in all_patterns:
try:
re.compile(pattern.get("regex", ""))
except re.error as e:
print(f" FAIL Pattern {pattern.get('id', 'UNKNOWN')}: Invalid regex - {e}")
return False
print(f" PASS All {len(all_patterns)} regex patterns compile successfully")
# Test 4: i18n completeness (FIXED: properly map error_key -> ERROR_KEYS -> SUGGESTIONS)
print("\nOK Test 4: i18n Completeness")
# Import ERROR_KEYS dict for proper mapping
import i18n
ERROR_KEYS_DICT = i18n.ERROR_KEYS
# First check: all pattern error_keys must exist in ERROR_KEYS
for pattern in all_patterns:
error_key = pattern.get("error_key", "")
if error_key not in ERROR_KEYS_DICT:
print(f" FAIL Pattern {pattern.get('id', 'UNKNOWN')}: error_key '{error_key}' not in i18n.ERROR_KEYS")
return False
# Second check: all mapped suggestion_keys must have translations in all languages
for lang in SUPPORTED_LANGUAGES:
if lang not in suggestions:
print(f" FAIL Language '{lang}' not found in SUGGESTIONS")
return False
missing_patterns = []
for pattern in all_patterns:
error_key = pattern.get("error_key", "")
# Map error_key to actual suggestion_key via ERROR_KEYS dict
# Example: "TYPE_MISMATCH" -> "type_mismatch"
suggestion_key = ERROR_KEYS_DICT.get(error_key)
if suggestion_key is None:
# Shouldn't happen since we checked above
missing_patterns.append(f"{pattern.get('id', 'UNKNOWN')} (no mapping for '{error_key}')")
continue
# Check if the mapped suggestion_key exists in this language's SUGGESTIONS
if suggestion_key not in suggestions[lang]:
missing_patterns.append(f"{pattern.get('id', 'UNKNOWN')} ({error_key} -> {suggestion_key})")
if missing_patterns:
print(f" FAIL {lang}: {len(missing_patterns)} patterns missing translations:")
for mp in missing_patterns[:5]: # Show first 5
print(f" - {mp}")
if len(missing_patterns) > 5:
print(f" ... and {len(missing_patterns) - 5} more")
return False
else:
print(f" PASS {lang}: All {len(all_patterns)} patterns have translations")
# Test 5: Priority ranges
print("\nOK Test 5: Priority Ranges (50-95)")
for pattern in all_patterns:
priority = pattern.get("priority", 0)
if not isinstance(priority, int) or not (50 <= priority <= 95):
print(f" FAIL Pattern {pattern.get('id', 'UNKNOWN')}: Invalid priority {priority}")
return False
print(f" PASS All priorities valid")
# Test 6: Unique IDs
print("\nOK Test 6: Unique Pattern IDs")
seen_ids = {}
for pattern in all_patterns:
pattern_id = pattern.get("id", "UNKNOWN")
if pattern_id in seen_ids:
print(f" FAIL Duplicate ID '{pattern_id}' in:")
print(f" - {seen_ids[pattern_id]}")
print(f" - {pattern['_source_file']}")
return False
seen_ids[pattern_id] = pattern["_source_file"]
print(f" PASS All {len(all_patterns)} pattern IDs are unique")
# Test 7: Valid categories
print("\nOK Test 7: Valid Categories")
for pattern in all_patterns:
category = pattern.get("category", "")
if category not in VALID_CATEGORIES:
print(f" FAIL Pattern {pattern.get('id', 'UNKNOWN')}: Invalid category '{category}'")
print(f" Valid: {', '.join(sorted(VALID_CATEGORIES))}")
return False
print(f" PASS All categories valid")
# Statistics
print("\nINFO: Pattern Statistics")
print("="*70)
print(f"Total patterns: {len(all_patterns)}")
by_category = {}
by_source = {}
for pattern in all_patterns:
category = pattern.get("category", "unknown")
source_file = pattern["_source_file"]
by_category[category] = by_category.get(category, 0) + 1
by_source[source_file] = by_source.get(source_file, 0) + 1
print("\nBy category:")
for cat, count in sorted(by_category.items()):
print(f" {cat:20s}: {count}")
print("\nBy source file:")
for src, count in sorted(by_source.items()):
print(f" {src:40s}: {count}")
print("\n" + "="*70)
print("PASS ALL TESTS PASSED!")
print("="*70)
return True
if __name__ == "__main__":
success = run_tests()
sys.exit(0 if success else 1)