test(m1): add conftest fixtures and golden helpers
This commit is contained in:
parent
aa7fe4b553
commit
d0be8fba11
5 changed files with 369 additions and 0 deletions
100
tests/conftest.py
Normal file
100
tests/conftest.py
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
"""Shared fixtures for the whole suite (plan Step 6).
|
||||
|
||||
Determinism here is a property of the interface, not of the harness. Tests get
|
||||
`frozen_today` and pass it to scripts as `--today`; nothing monkeypatches
|
||||
`datetime`. The difference matters: a script that only behaves deterministically
|
||||
because a test patched the clock is a script whose callers cannot make it
|
||||
behave deterministically at all, and `dagens` (build-brief 5.8) has to be
|
||||
reproducible from the command line.
|
||||
|
||||
The autouse `fixtures_are_pristine` guard exists because the failure it catches
|
||||
does not announce itself. A test that writes into `tests/fixtures/` leaves
|
||||
every later run reading a corpus that no longer matches what it says it is, and
|
||||
the eventual failure surfaces in some unrelated test hours later. Catching it
|
||||
at the end of the offending test names the culprit.
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
|
||||
from helpers import golden as golden_helper
|
||||
from helpers import workspace as workspace_helper
|
||||
|
||||
from jobbsok_lib import paths
|
||||
|
||||
FIXTURES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures")
|
||||
|
||||
#: Every date in the corpus is relative to this. 2026-09-15 is a Tuesday, so
|
||||
#: weekday-sensitive output does not accidentally land on a weekend.
|
||||
FROZEN_TODAY = workspace_helper.FROZEN_TODAY
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption(
|
||||
"--update-golden",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="rewrite golden files instead of comparing against them",
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fixtures_dir():
|
||||
"""Absolute path to the read-only fixture corpus."""
|
||||
return FIXTURES_DIR
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def frozen_today():
|
||||
"""The date the suite reasons from, passed to scripts as ``--today``."""
|
||||
return FROZEN_TODAY
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def empty_workspace(tmp_path):
|
||||
"""A scaffolded but empty build-brief section 5 workspace."""
|
||||
root = str(tmp_path / "workspace")
|
||||
paths.scaffold(root)
|
||||
return root
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def workspace(empty_workspace):
|
||||
"""A workspace with the fixture corpus copied in, when there is one.
|
||||
|
||||
The populated corpus arrives in plan Step 19; until then this is the
|
||||
scaffolded tree, so tests written against it now keep working when the
|
||||
corpus lands rather than being rewritten then.
|
||||
"""
|
||||
source = os.path.join(FIXTURES_DIR, "workspace")
|
||||
if os.path.isdir(source):
|
||||
shutil.copytree(source, empty_workspace, dirs_exist_ok=True)
|
||||
return empty_workspace
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def golden(request):
|
||||
"""`assert_golden` with the ``--update-golden`` flag already bound."""
|
||||
update = request.config.getoption("--update-golden")
|
||||
|
||||
def compare(path, actual):
|
||||
return golden_helper.assert_golden(path, actual, update=update)
|
||||
|
||||
return compare
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def fixtures_are_pristine(request):
|
||||
"""Fail the test that mutated the read-only corpus, at that test."""
|
||||
if not os.path.isdir(FIXTURES_DIR):
|
||||
yield
|
||||
return
|
||||
if request.config.getoption("--update-golden"):
|
||||
# Golden regeneration is the one sanctioned write into the corpus.
|
||||
yield
|
||||
return
|
||||
before = workspace_helper.snapshot_tree(FIXTURES_DIR)
|
||||
yield
|
||||
workspace_helper.assert_tree_unchanged(FIXTURES_DIR, before)
|
||||
Loading…
Add table
Add a link
Reference in a new issue