Skip to content

Development

Testing & mutation contract

Tests follow a three-tier naming convention:

  • test_* — behavioural unit tests of the public API.
  • test_mut_* — mutation-killing tests written to pin specific mutants.
  • test_mut_*_floor — the floor tests that hold a module's mutation score at or above its ratchet baseline.

The library holds a per-module mutation-score floor (killed / total mutants), enforced by the ratchet. The gate itself is mutmut-ratchet, a shared package: it scopes a PR's mutation run to the modules the diff could affect, fans the work across time-balanced shards, and fails only on a real per-file regression against the committed scripts/mutation_baseline.json. Its per-repo settings — the package path, the escalation triggers, and the test -> source overrides for tests whose name does not map 1:1 to a module — live in [tool.mutmut_ratchet] in pyproject.toml.

Local commands

uv-first — there are no requirements*.txt files; dev/test tooling lives in pyproject.toml's [dependency-groups] and is locked in uv.lock:

uv sync --dev            # create the venv + install dev/test tooling from uv.lock
# or: bash scripts/setup.sh

uv run pytest -n auto                                   # run the test suite (parallel)
uv run ruff check . && uv run ruff format --check .     # lint + format
uv run mypy pyrtl_433/                                  # strict type check
uv run mutmut run                                       # mutation testing
uv run mutmut-ratchet stats > stats.json                # collect per-module stats
uv run mutmut-ratchet ratchet --mode floor --stats stats.json   # enforce the floor
uv run mutmut-ratchet ratchet --mode strict --stats stats.json  # check the baseline is current

After a full mutmut run, --update ratchets the committed baseline upward and mutmut-ratchet timings refreshes the shard weights:

uv run mutmut-ratchet ratchet --mode floor --stats stats.json --update
uv run mutmut-ratchet timings

Continuous integration

CI runs the same gates (lint, format, strict mypy, tests with a 95% coverage floor, and the mutation-score ratchet) on every push and pull request via GitHub Actions — see .github/workflows/.