60 lines
2.6 KiB
Python
60 lines
2.6 KiB
Python
"""S2.5 (Step 9) consolidation guard (T-2.5e): the four scripted ``_inner_get_response`` bodies
|
|
collapsed to ONE canonical client (``simulation.ScriptedChatClient``); conftest's three test doubles
|
|
now SUBCLASS it. These grep-guards lock that in — they go RED if a divergent ``_inner_get_response``
|
|
is re-added, if a ``src``→``tests`` import creeps in, or if a double stops subclassing the canonical.
|
|
|
|
The guard is a regression lock over an already-verified consolidation: before the collapse there were
|
|
five ``def _inner_get_response`` sites (four scripted + test_step5's own-lineage double); after, two.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
_ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def _py_files(base: str) -> list[Path]:
|
|
return sorted((_ROOT / base).rglob("*.py"))
|
|
|
|
|
|
def test_inner_get_response_collapsed_to_two_sites() -> None:
|
|
"""The four scripted clients collapse to ONE canonical ``_inner_get_response`` (simulation.py);
|
|
test_step5's own-lineage double is the only other def. So exactly 2 def-sites remain — NOT 5."""
|
|
sites = [
|
|
p.relative_to(_ROOT).as_posix()
|
|
for base in ("src", "tests")
|
|
for p in _py_files(base)
|
|
if p.name != Path(__file__).name # this guard file references the pattern in prose
|
|
and "def _inner_get_response" in p.read_text(encoding="utf-8")
|
|
]
|
|
assert sorted(sites) == [
|
|
"src/portfolio_optimiser/simulation.py",
|
|
"tests/test_step5_refine_loadbearing.py",
|
|
], f"expected the four scripted bodies collapsed to one canonical + test_step5's, got: {sites}"
|
|
|
|
|
|
def test_no_src_imports_tests() -> None:
|
|
"""No ``src`` module imports from ``tests`` — the canonical lives in ``src/simulation.py`` so
|
|
``conftest`` imports ``src``, never the reverse (the forbidden src→tests direction)."""
|
|
offenders = [
|
|
p.relative_to(_ROOT).as_posix()
|
|
for p in _py_files("src")
|
|
if ("from tests" in (text := p.read_text(encoding="utf-8")) or "import tests" in text)
|
|
]
|
|
assert offenders == [], f"src must not import tests: {offenders}"
|
|
|
|
|
|
def test_conftest_doubles_subclass_canonical() -> None:
|
|
"""conftest's three test doubles genuinely SUBCLASS the canonical ``ScriptedChatClient``
|
|
(delegating the shared body) — so the consolidation is real, not cosmetic."""
|
|
from conftest import (
|
|
ScriptedChatClient,
|
|
SyntheticUsageChatClient,
|
|
_ProjectAwareUsageChatClient,
|
|
_RecordingChatClient,
|
|
)
|
|
|
|
assert issubclass(SyntheticUsageChatClient, ScriptedChatClient)
|
|
assert issubclass(_ProjectAwareUsageChatClient, ScriptedChatClient)
|
|
assert issubclass(_RecordingChatClient, ScriptedChatClient)
|