proejct commit
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
"""Architektur-Tests: Die Physik-Schicht bleibt frei von pygame und fremden Bibliotheken.
|
||||
|
||||
Anforderung: Die gesamte Physik darf nur das Standardmodul ``math`` verwenden
|
||||
(zusätzlich ``typing``/``dataclasses`` für Typangaben und Datenstrukturen). Diese Tests
|
||||
prüfen das statisch über den Syntaxbaum und zur Laufzeit in einem frischen Interpreter.
|
||||
"""
|
||||
|
||||
import ast
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
SOURCE_ROOT = Path(__file__).resolve().parents[1] / "src" / "sandbox"
|
||||
PHYSICS_FILES = sorted((SOURCE_ROOT / "physics").glob("*.py"))
|
||||
PURE_FILES = [*PHYSICS_FILES, SOURCE_ROOT / "config.py"]
|
||||
|
||||
ALLOWED_STDLIB = {"__future__", "math", "typing", "dataclasses"}
|
||||
ALLOWED_PROJECT = {"sandbox.config"}
|
||||
|
||||
|
||||
def _imported_modules(path: Path) -> set[str]:
|
||||
tree = ast.parse(path.read_text(encoding="utf-8"))
|
||||
modules: set[str] = set()
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
modules.update(alias.name for alias in node.names)
|
||||
elif isinstance(node, ast.ImportFrom):
|
||||
modules.add(node.module or "")
|
||||
return modules
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path", PURE_FILES, ids=lambda path: path.name)
|
||||
def test_physics_and_config_import_only_allowed_modules(path: Path) -> None:
|
||||
forbidden = {
|
||||
module
|
||||
for module in _imported_modules(path)
|
||||
if module not in ALLOWED_STDLIB
|
||||
and module not in ALLOWED_PROJECT
|
||||
and not module.startswith("sandbox.physics")
|
||||
}
|
||||
assert not forbidden, f"{path.name} importiert nicht erlaubte Module: {forbidden}"
|
||||
|
||||
|
||||
def test_physics_files_were_found() -> None:
|
||||
assert len(PHYSICS_FILES) >= 8
|
||||
|
||||
|
||||
def test_importing_the_physics_package_does_not_load_pygame() -> None:
|
||||
code = "import sys, sandbox.physics, sandbox.config; print('pygame' in sys.modules)"
|
||||
result = subprocess.run(
|
||||
[sys.executable, "-c", code],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
env={**os.environ, "PYTHONPATH": str(SOURCE_ROOT.parent)},
|
||||
)
|
||||
assert result.stdout.strip() == "False"
|
||||
Reference in New Issue
Block a user