Test Suites and Runtime¶
The 2026-08-10 documentation audit collected 596 tests: 591 in the fast tier and five in the slow tier. On the audited checkout, the fast pytest run completed in 70.97 seconds (74.79 seconds including runner startup), and the slow pytest run completed in 44.56 seconds (47.13 seconds including startup). Treat these as a local warm-cache snapshot rather than a performance budget.
The five slow cases are one deterministic-bandit IPPO integration, one Markov Stag Hunt exact-graph build, two IPPO-Lagrangian trainer integrations, and one shielded IPPO integration. Cold JAX and exact-graph caches can make absolute timings longer, but CI runs the fast and slow shards in parallel so those costs are not serialized.
Use the repository runner during development:
# Select non-slow tests from tracked and untracked working-tree changes.
uv run python scripts/run_tests.py changed
# Broad non-slow regression suite.
uv run python scripts/run_tests.py fast
# One ownership group, excluding slow tests by default.
uv run python scripts/run_tests.py world_model
# Include that component's expensive integrations.
uv run python scripts/run_tests.py shield --include-slow
# Expensive tier only, or every test.
uv run python scripts/run_tests.py slow
uv run python scripts/run_tests.py full
changed compares the working tree to HEAD. Pass --base origin/main to
include committed branch changes, or repeat --changed-file PATH to use an
explicit set. Arguments after -- are forwarded to pytest.
Change-to-suite map¶
Every test module has one primary marker in tests/suite_manifest.py.
Collection fails if a new test_*.py module has not been classified. Manifest
keys are relative to tests/, so nested notebook suites are supported.
| Changed code | Routine suite | Include slow when |
|---|---|---|
src/core/ |
core |
normally unnecessary |
src/environments/ |
env |
exact environment graphs or long rollouts change |
src/world_model/ |
world_model |
model training or a large graph projection changes |
src/opponent_model/ |
opponent_model |
imagination or policy-improvement loops change |
src/joint_graph/ |
joint_graph |
exact graph enumeration changes |
src/shield/, src/true_shield/ |
shield |
shielded trainer integration changes |
src/rl/ |
rl |
trainer construction or update loops change |
notebooks/ |
experiments |
real notebook execution or exports change |
src/visualisation/ |
visualisation |
plot or export behavior changes |
a tests/**/test_*.py file |
that exact file | the edited test has the slow marker |
| dependency, pytest, CI, or unknown implementation configuration | fast |
use full if integrations may change |
| documentation only | no pytest selection | run uv run zensical build --strict |
Some files are explicitly cross-cutting. In particular, labelled environment logging selects environment, RL, shield, and visualisation tests; graph augmentation selects joint-graph, world-model, and opponent-model tests.
CI runs fast and slow as parallel jobs. Together they preserve complete
coverage while allowing ordinary deterministic failures to return earlier.
The JAX persistent compilation cache lives under
.cache/jax-test-compilation, which is already ignored.
Runtime policy¶
The slow marker is reserved for measured tests near or above ten seconds,
not tests that merely look complex. Slow tests receive a 180-second timeout;
normal tests retain the 60-second project default. Re-profile before changing
the manifest:
Prefer small deterministic contract tests and fixture reuse over adding more slow integrations. Component ownership describes the test's primary purpose, not the absence of dependencies on other components.