Testing Standards#
Test requirements at three levels, all enforced by CI.
1. Unit Tests (mandatory for all code)#
Location: tests/<module>/test_<name>.py
Requirements:
Test each public method
Test normal operation and edge cases
For nodes: verify JAX-traceability (
jax.jit,jax.grad,jax.vmap)Test boundary input handling (missing inputs, default values)
Test parameter edge cases
def test_your_node_basic():
node = YourNode("test", timestep=0.01)
state = node.initial_state()
new_state = node.update(state, {}, 0.01)
assert "field" in new_state
def test_your_node_jit():
node = YourNode("test", timestep=0.01)
state = node.initial_state()
jitted = jax.jit(node.update)
new_state = jitted(state, {}, 0.01)
# Must not raise
2. Integration Tests (mandatory for nodes)#
Test the node within a GraphManager:
def test_your_node_in_graph():
gm = GraphManager()
node = YourNode("test", timestep=0.01)
gm.add_node(node)
state = gm.run(n_steps=10)
assert "test" in state
Test edge connections if the node consumes or produces coupled data.
3. Verification Benchmarks (mandatory for physics nodes)#
Location: tests/verification/test_<name>_<benchmark>.py
Compare against analytical solutions or published reference data. Register with the @verification_benchmark decorator:
from maddening.core.validation import verification_benchmark
@verification_benchmark(
benchmark_id="MADD-VER-XXX",
description="Analytical solution comparison for ...",
node_class="YourNode",
reference="AuthorYear",
)
def test_your_node_analytical():
"""Compare YourNode output to analytical solution."""
node = YourNode("bench", timestep=0.001, ...)
gm = GraphManager()
gm.add_node(node)
state = gm.run(n_steps=1000)
# Compute analytical solution
analytical = ...
# Compare
error = jnp.abs(state["bench"]["field"] - analytical)
assert jnp.max(error) < tolerance, f"Max error {jnp.max(error)} exceeds {tolerance}"
Verification benchmarks must:
Use a registered benchmark ID (
MADD-VER-XXX)Cite the analytical solution or reference data source
State the tolerance and justify it
Be referenced in the node’s algorithm guide (Verification Evidence section)
Running Tests#
# Activate venv
source ../venvs/.maddening/bin/activate
# Full test suite (exclude viz — requires display)
PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python -m pytest tests/ -v --tb=short --ignore=tests/viz
# Just compliance + verification
python -m pytest tests/compliance/ tests/verification/ -v --tb=short
# Just your new node's tests
python -m pytest tests/nodes/test_your_node.py tests/verification/test_your_node_*.py -v
# Compliance CI scripts
python scripts/check_anomalies.py
python scripts/check_impl_mapping.py
python scripts/check_citations.py
Environment Variables#
Variable |
Purpose |
Typical Value |
|---|---|---|
|
Force CPU backend (avoids GPU issues) |
|
|
Disable GPU autotune (avoids equinox segfaults) |
|
|
Prevent plugin conflicts |
|
Test Organization#
tests/
├── core/ # GraphManager, scheduling, coupling, adaptive, checkpoint
├── nodes/ # Per-node unit tests
├── surrogates/ # Surrogate framework tests
├── api/ # Server, WebSocket, binary encoder tests
├── viz/ # Visualization tests (skipped in CI — require display)
├── compliance/ # Metadata, anomaly registry, stability tests
└── verification/ # Analytical benchmarks (registered with @verification_benchmark)
pytest Configuration#
Test warnings are escalated to errors by default (filterwarnings = ["error"] in pyproject.toml). Known-safe warnings are explicitly ignored. If your code produces a new warning, either fix the cause or add a documented filter to pyproject.toml with a comment explaining why.