Skip to content

Mutation-test survivors in scripts/launcher_deps.py and scripts/generate_pip_constraints.py (85 + 65), now that #262 makes them measurable #263

Description

@cdeust

Context

Issue #262 fixed mutation testing's inability to attribute mutants for any
scripts/ module — every tests_py/scripts/*.py test loaded its subject
under a synthetic/bare module name (_cortex_launcher_deps,
generate_pip_constraints, etc.), while mutmut keys mutant trampolines on
the path-derived dotted name (scripts.launcher_deps,
scripts.generate_pip_constraints). The fix renamed every affected test's
module handle to the dotted path mutmut expects, and widened
[tool.mutmut] also_copy to include uv.lock, requirements/, and
pyproject.toml (files generate_pip_constraints.py's test reads).

That PR did not change either module's own source — only how tests load
it — so it could not itself fix any of the survivors mutation testing now
reveals. Precedent for exactly this split: PR #236 ("make scripts/
mutation-reachable") filed its own discovered survivors as #235 rather than
folding an unrelated, much larger test-writing effort into the attribution
fix.

What mutation testing now shows (real tallies, not an early abort)

scripts/launcher_deps.py against tests_py/scripts/test_launcher_deps.py:
213 mutants, 128 killed, 85 survived, 0 no-tests, 0 timeout.

Concentrated in the orchestration/I-O functions the existing suite does not
exercise at the mutant-detection level: _importable (husk-detection
branches), _pins_satisfied (stamp/pin-set comparison edges),
_write_stamp, ensure_deps, and ensure_all_deps (lock/double-check/
constraint-passing branches).

scripts/generate_pip_constraints.py against
tests_py/scripts/test_generate_pip_constraints.py: 243 mutants, 95 killed,
65 survived, 83 no-tests (code paths, largely inside export()'s
uv subprocess plumbing and main()'s non---check write path, that the
current suite never calls at all — a coverage gap, not just a detection
gap).

Concentrated in declared_index_urls, lock_registries, serving_registries,
compose, _reject_unusable, stale, and main (mostly its non---check
branches and message-formatting edges).

Acceptance criteria

  1. Re-run scripts/mutation_check.sh tests_py/scripts/test_launcher_deps.py scripts/launcher_deps.py
    and scripts/mutation_check.sh tests_py/scripts/test_generate_pip_constraints.py scripts/generate_pip_constraints.py.
  2. Every surviving mutant in both files is triaged per coding-standards.md
    §12.4: killed by a new/strengthened test, or documented as a provable
    equivalent (comment at the mutant's line — same observable behavior,
    e.g. a comparison operator flip on an unreachable branch).
  3. The 83 no-tests mutants in generate_pip_constraints.py get real
    coverage first (a mutant nothing executes cannot be triaged as
    killed/equivalent) — likely via a stubbed/faked uv subprocess for
    export()'s currently-untested lines, and a main() non---check
    (write) path test.
  4. Final state: 0 survivors in both files (per §12.4), tracked via
    scripts/mutation_check.sh.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions