Skip to content

Split the tongs and anvil test modules to mirror their packages - #40

Merged
CrypticSwarm merged 4 commits into
masterfrom
tests-mirror-module-split
Aug 6, 2026
Merged

Split the tongs and anvil test modules to mirror their packages#40
CrypticSwarm merged 4 commits into
masterfrom
tests-mirror-module-split

Conversation

@CrypticSwarm

Copy link
Copy Markdown
Owner

tests/test_tongs.py and tests/test_run_anvil.py had each grown past 1900 lines, covering every module of the package they tested. A change to one concern meant opening a file mostly about the other eight. Both now mirror the package they cover: a test module is named for the source module it exercises, so the file that covers a change is the one named after it.

swarmforge/tongs/<module>.py  ->  tests/test_tongs_<module>.py   (10 modules)
swarmforge/anvil/<module>.py  ->  tests/test_anvil_<module>.py   (5 modules)

Two anvil modules get no file of their own, and the README says why rather than leaving the naming rule reading as a promise the tree does not keep: readiness is exercised through run_with_tongs, and errors holds one exception class.

Nothing about the tests changed

Every test body is byte-identical to what it replaced, verified by comparing the source text of all 423 functions, methods, constants, and fake classes between the old files and the new ones. The suite collects the same 495 tests and passes.

One class did move. The tong_mount_specs and workspace_mount_placements cases had accumulated inside DockerArgvTests; they exercise mounts, not argv, and are now MountSpecTests alongside the rest of the mount grammar. The bodies are unchanged — only the enclosing class name.

The passthrough invariant — no tongs discovered means the anvil argv is exec'd byte-for-byte — is still asserted, now from tests/test_anvil_cli.py next to the other cases that drive bin/run-anvil as a subprocess. The docstring in swarmforge/anvil/__init__.py that points at it was updated to match.

Shared fixtures

Tong definitions and stubs that more than one test module needs live in tests/tongs_fixtures.py and tests/anvil_fixtures.py. The test_*.py discovery glob skips them, so they are not collected as suites of their own; fixtures used by a single module stay with it.

Because those are sibling modules imported by name, the tests directory has to be on sys.path. Discovery and python3 tests/<file>.py both put it there; python3 -m unittest tests.<module> does not, so every file that imports a fixture module puts it there itself. All three invocation forms work for all 15 files.

No new dependencies — still stdlib only.

`test_tongs.py` had grown to 1900 lines covering every module in
`swarmforge/tongs/`, so a change to one concern meant opening a file
mostly about the other eight. It now mirrors the package: one
`test_tongs_<module>.py` per source module, so the file that covers a
change is the one named after it.

Test bodies are unchanged. The only class that moved is the block of
`tong_mount_specs` and `workspace_mount_placements` cases that had
accumulated inside `DockerArgvTests`; they exercise `mounts`, not
`argv`, and are now `MountSpecTests` alongside the rest of the mount
grammar.

Tong definitions more than one module needs -- and the `def_of` helper
that parses them -- move to `tests/tongs_fixtures.py`. The discovery
glob is `test_*.py`, so the fixtures module is not collected as a suite
of its own; ones used by a single module stay with it.
Same treatment for the launcher's 1900-line `test_run_anvil.py`: one
`test_anvil_<module>.py` per module in `swarmforge/anvil/`, so the
orchestration tests stop sharing a file with argument parsing and the
docker wrapper.

Test bodies are unchanged and every class keeps its name. The
passthrough invariant -- no tongs discovered means the anvil argv is
exec'd byte-for-byte -- now lives in `test_anvil_cli.py`, next to the
other cases that drive `bin/run-anvil` as a subprocess.

`ANVIL_ARGV` and the `_merged` helper are needed by more than one of
the new modules and move to `tests/anvil_fixtures.py`, which the
`test_*.py` discovery glob skips. `readiness` gets no file of its own:
it is covered through `run_with_tongs`, and an empty module would only
claim otherwise.
Two package docstrings named test files that no longer exist, and
neither the README nor AGENTS.md said where a given test now lives.
Both now state that a test module is named for the source module it
covers, and name the fixture modules the discovery glob deliberately
skips, so nobody adds a `test_`-prefixed helper and wonders why it runs.

The README also names the two anvil modules with no test file of their
own -- `readiness`, exercised through `run_with_tongs`, and `errors`,
which is one exception class -- so the naming rule does not read as a
promise the tree does not keep.
Splitting the suites introduced `tongs_fixtures` / `anvil_fixtures` as
sibling modules, imported by name. Discovery and `python3 tests/<file>.py`
both put the tests directory on `sys.path`, but `python3 -m unittest
tests.<module>` puts only the repo root there -- so running one split
file that way failed on the fixture import, while an untouched file like
`test_git_guard` still worked. Put the tests directory on the path
alongside the repo root in every file that imports a fixture module.

Also drop the module-level `import shutil` from the approval tests: the
one use it had went to the orchestration tests, and the `tearDown` left
behind imports `shutil` locally.
@CrypticSwarm
CrypticSwarm merged commit 9d62e06 into master Aug 6, 2026
3 checks passed
@CrypticSwarm
CrypticSwarm deleted the tests-mirror-module-split branch August 6, 2026 06:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant