Files
pygame-physics-opus5.5/tests/test_architecture.py
T
2026-09-24 15:45:31 +02:00

61 lines
2.0 KiB
Python

"""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"