Fix mutmut baseline crash on cwd-relative tests (#196) - #198
Conversation
mutmut instruments every mutated call with a trampoline that resolves
`[tool.mutmut] source_paths` ("lading/") against the current working
directory, with strict=True, on every hit
(mutmut/__main__.py::record_trampoline_hit). Five unit tests chdir into
a bare tmp_path to exercise cwd-relative path resolution (workspace-root
defaulting, relative build directories); doing so starves that lookup
of a "lading" directory and crashes mutmut's baseline with
FileNotFoundError before any mutants are generated.
Add tests/helpers/cwd.py::chdir_for_test, a drop-in replacement for
monkeypatch.chdir(tmp_path) that pre-creates a "lading" placeholder
directory so the trampoline's existence check succeeds regardless of
harness, and route the five affected call sites through it.
Reproduced locally with `uv run --with mutmut==3.6.0 mutmut run`:
baseline failed deterministically before this change and passes after.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Our agent can fix these. Install it.
Gates Passed
6 Quality Gates Passed
Absence of Expected Change Pattern
- lading/tests/unit/test_cli.py is usually changed with: lading/lading/cli.py, lading/lading/commands/bump.py
Quality Gate Profile: Pay Down Tech Debt
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.
Summary
pytestrun has never completed for lading: it aborteddeterministically on
test_run_normalises_workspace_root(
tests/unit/publish/test_run_workspace_config.py) withFileNotFoundError, treated as a fatal error by mutmut(
mutation_mutmut_error=mutmut run failed with exit code 1 (failing baseline?)), so no mutants were ever generated.uv run --with mutmut==3.6.0 mutmut run): mutmut instruments every mutatedcall with a trampoline that resolves
[tool.mutmut] source_paths(
"lading/") against the current working directory, withstrict=True, on every hit(
mutmut/__main__.py::record_trampoline_hit). Five unit tests callmonkeypatch.chdir(tmp_path)to exercise cwd-relative path resolution(workspace-root defaulting, relative build directories). Chdir'ing into a
bare
tmp_pathstarves that lookup of a "lading" directory and crashesthe trampoline with
FileNotFoundError— not atmp_pathrace, as theissue's title suggested; the failure is 100% deterministic whenever the
baseline actually executes one of these tests.
tests/helpers/cwd.py::chdir_for_test(monkeypatch, path), adrop-in replacement for
monkeypatch.chdir(path)that pre-creates a"lading"placeholder directory so the trampoline's existence checksucceeds regardless of harness. It is inert under plain
pytest, where nosuch instrumentation exists. Routed all five affected call sites through
it:
tests/unit/publish/test_run_workspace_config.pytests/unit/test_bump_manifest_updates.pytests/unit/test_publish_staging.pytests/unit/test_cli.py(two call sites)/mutants/,.mutmut-cache), discovered untracked while reproducing this issuelocally; cargo-mutants'
mutants.out*/was already ignored but mutmut'sown directory was not.
Closes #196
Why not exclude the test instead
Excluding
test_run_normalises_workspace_root(or disabling the cwd-relatedassertion) would have been the easy way out, but the chdir is the point of
the test: it verifies that
publish.run(and the equivalentbump/CLIhelpers) resolve relative workspace-root arguments against the process's
current working directory. That is real, load-bearing behaviour. The actual
defect is an incidental interaction between that legitimate test behaviour
and mutmut's own trampoline instrumentation, which is fully addressed by
giving the trampoline the directory it expects, without changing what the
tests assert.
Validation
Reproduced with
uv run --with mutmut==3.6.0 mutmut runfrom a cleanmutants//.mutmut-cachestate:Before (red): baseline stats collection aborts —
FAILED tests/unit/publish/test_run_workspace_config.py::test_run_normalises_workspace_rootwith
FileNotFoundError: ... /test_run_normalises_workspace_0/lading,failed to collect stats. runner returned 1.After (green) for the five originally-crashing call sites: the same
baseline run no longer fails on any of them; mutmut's "Running stats" phase
completes the full suite (718 passed, 6 skipped).
Separate, unrelated finding (not fixed here, not part of #196): mutmut's
baseline additionally re-runs the full suite a second time in the same
process ("Running clean tests"), and Python does not support repeated
in-process
pytest.main()invocations cleanly — Hypothesis raisesFailedHealthCheck: differing_executorson the second pass, and a stalelogging handler from the first pass causes an unrelated
test_cmd_mox_passthrough_streams_outputassertion to fail. Reproduced thisdirectly (without mutmut) by calling
pytest.main()twice in one process.This is a distinct, deeper defect in how mutmut's baseline is structured/
configured for Hypothesis-using suites, out of scope for this PR; noted for
the orchestrator to file as a follow-up.
Standard gates (
make lint,make check-fmt,make typecheck,make test) run via the project's commit-gate process; see CI status on this PR.Review walkthrough
tests/helpers/cwd.py— new shared helper, with a comment explaining the mutmut interaction.tests/unit/publish/test_run_workspace_config.py— the originally-reported test, now using the helper.tests/unit/test_bump_manifest_updates.py,tests/unit/test_publish_staging.py,tests/unit/test_cli.py— the other four vulnerable call sites, same fix..gitignore— ignore mutmut's local working copy.