pre_rules_tests.py
- Pfad:
/var/www/tools/ki-protokoll/claude-hook/quality/pre_rules_tests.py - Namespace: claude-hook.quality
- Zeilen: 137 | Größe: 4,456 Bytes
- Geändert: 2025-12-28 12:53:55 | Gescannt: 2025-12-31 10:22:15
Code Hygiene Score: 100
- Dependencies: 100 (25%)
- LOC: 100 (20%)
- Methods: 100 (20%)
- Secrets: 100 (15%)
- Classes: 100 (10%)
- Magic Numbers: 100 (10%)
Keine Issues gefunden.
Dependencies 3
- use re
- use typing.Optional
- use rule_base.block
Funktionen 4
-
is_test_file()Zeile 60 -
p14_production_database()Zeile 69 -
p14_dangerous_operations()Zeile 85 -
p14_shared_state()Zeile 98
Code
#!/usr/bin/env python3
"""
Pre-Hook Test Isolation Regeln (BLOCK) - Test Isolation.
P14.x Regeln: Erzwingt Test-Isolation durch Blockieren von Produktions-DB-Zugriff.
Prinzip: "Tests beeinflussen sich nicht gegenseitig. Globaler Zustand ist kontrolliert."
WICHTIG: Diese Regeln gelten NUR für Test-Dateien (/tests/, /Test/).
"""
import re
from typing import Optional
from .rule_base import block
# =============================================================================
# KONFIGURATION
# =============================================================================
# Pfade die als Test-Dateien gelten
TEST_PATHS = ["/tests/", "/Test/"]
# Produktions-Datenbanken (ohne _test Suffix)
PRODUCTION_DATABASES = {
"P14.1": {
"pattern": r"['\"]ki_content['\"]",
"exclude_pattern": r"['\"]ki_content_test['\"]",
"message": "Production database 'ki_content' used in tests. Use 'ki_content_test' instead.",
},
"P14.2": {
"pattern": r"['\"]ki_dev['\"]",
"exclude_pattern": r"['\"]ki_dev_test['\"]",
"message": "Production database 'ki_dev' used in tests. Use 'ki_dev_test' instead.",
},
"P14.3": {
"pattern": r"['\"]ki_protokoll['\"]",
"exclude_pattern": r"['\"]ki_protokoll_test['\"]",
"message": "Production database 'ki_protokoll' used in tests. Use 'ki_protokoll_test' instead.",
},
}
# Gefährliche Operationen in Tests
DANGEROUS_TEST_PATTERNS = {
"P14.4": {
"pattern": r"TRUNCATE\s+TABLE",
"message": "TRUNCATE TABLE in tests. Use test fixtures or transactions instead.",
},
"P14.5": {
"pattern": r"DROP\s+(?:TABLE|DATABASE)",
"message": "DROP TABLE/DATABASE in tests. Never drop in tests.",
},
}
# =============================================================================
# HELPER
# =============================================================================
def is_test_file(file_path: str) -> bool:
"""Prüft ob die Datei eine Test-Datei ist."""
return any(test_path in file_path for test_path in TEST_PATHS)
# =============================================================================
# REGELN
# =============================================================================
def p14_production_database(file_path: str, content: str) -> Optional[dict]:
"""P14.1-P14.3: Produktions-Datenbank in Tests blockieren."""
# Nur für Test-Dateien prüfen
if not is_test_file(file_path):
return None
for rule_id, config in PRODUCTION_DATABASES.items():
# Suche nach Produktions-DB
if re.search(config["pattern"], content):
# Prüfe ob es die Test-Variante ist
if not re.search(config["exclude_pattern"], content):
return block(rule_id, config["message"])
return None
def p14_dangerous_operations(file_path: str, content: str) -> Optional[dict]:
"""P14.4-P14.5: Gefährliche Operationen in Tests blockieren."""
# Nur für Test-Dateien prüfen
if not is_test_file(file_path):
return None
for rule_id, config in DANGEROUS_TEST_PATTERNS.items():
if re.search(config["pattern"], content, re.IGNORECASE):
return block(rule_id, config["message"])
return None
def p14_shared_state(file_path: str, content: str) -> Optional[dict]:
"""P14.6: Statische Properties ohne Reset in Tests."""
# Nur für Test-Dateien prüfen
if not is_test_file(file_path):
return None
# Prüfe auf static Properties die in Tests gesetzt werden
# ohne entsprechenden Reset in tearDown
static_assignments = re.findall(
r"self::\$\w+\s*=|static::\$\w+\s*=",
content
)
if static_assignments:
# Prüfe ob tearDown vorhanden ist
has_teardown = bool(re.search(
r"(?:protected|public)\s+function\s+tearDown\s*\(",
content
))
if not has_teardown:
return block(
"P14.6",
f"Static property assignment in tests ({len(static_assignments)}x) "
"without tearDown() method. Add tearDown() to reset static state."
)
return None
# =============================================================================
# RULE COLLECTION
# =============================================================================
RULES = [
p14_production_database,
p14_dangerous_operations,
p14_shared_state,
]