Skip to content

Mutation testing: git plumbing helper survivors #36

Description

@leynos

Context

Mutation-testing run against main (b850e2fec11b1966d2b73670ae56b5eff195284e), mutmut 3.6.0, local run 2026-07-10: 1025 mutants, 151 killed, 235 survived, 639 no-tests. All mutants target hooks/post-turn-quality-stop-hook.py.

This issue covers the git/make plumbing helpers: 102 survivors across repo_root, has_uncommitted_changes, get_upstream_ref, has_unpushed_commits, get_make_targets, and compush_check.

Surviving mutants

  • hooks/post-turn-quality-stop-hook.py:208 — every token of ["git", "rev-parse", "--show-toplevel"] mutates freely in repo_root (x_repo_root__mutmut_611); likewise the returncode check, error-string composition, and empty-output message (mutmut_1223).
  • hooks/post-turn-quality-stop-hook.py:482-493 — all argv tokens of git diff --quiet, git diff --cached --quiet, and git ls-files --others --exclude-standard in has_uncommitted_changes (x_has_uncommitted_changes__mutmut_143, 32 survivors), including run(args, None) argument-wiring mutants and the ' '.join(args) error format.
  • hooks/post-turn-quality-stop-hook.py:513-518 — the full git rev-parse --abbrev-ref --symbolic-full-name @{u} argv and error literals in get_upstream_ref (x_get_upstream_ref__mutmut_625, 16 survivors).
  • hooks/post-turn-quality-stop-hook.py:537-549 — the git rev-list --count argv in has_unpushed_commits (x_has_unpushed_commits__mutmut_217), and notably int(ahead) > 0> 1 (x_has_unpushed_commits__mutmut_21, line 549).
  • hooks/post-turn-quality-stop-hook.py:641-652 — the make -qp --no-print-directory argv, the returncode == 2 sentinel, and error composition in get_make_targets (x_get_make_targets__mutmut_222, 18 survivors).
  • hooks/post-turn-quality-stop-hook.py:1090-1106compush_check call wiring (has_uncommitted_changes(None), has_unpushed_commits(None, upstream) and permutations) and the upstream-label literal "origin (upstream not configured)" wrapped as XX…XX (x_compush_check__mutmut_5, 8, 2427).

Analysis

The test suite (hooks/test_post_turn_quality_stop_hook.py) patches hook.run wholesale and never asserts the argument vectors passed to it, so any mutation of a command list, of the run(args, repo) wiring, or of git-failure messages is invisible. Error-message tests use substring assertions ("fatal: bad" in err), so literal mutations that preserve the substring also survive — the XX…XX wrapping of the compush upstream label survives precisely because the test asserts in rather than equality. The > 0> 1 boundary survives because tests use ahead-counts 2 and 0, never 1.

Suggested tests

  1. In each mocked-run test, assert mock_run.call_args_list against the exact argv and repo argument (kills the ~85 argv and wiring mutants).
  2. Add a has_unpushed_commits case with rev-list output "1" asserting True (kills the > 1 boundary mutant).
  3. Assert exact error messages (or == on the blocked-payload reason) for repo_root, get_upstream_ref, get_make_targets, and the compush fallback label (kills the literal-mutation survivors).
  4. Optionally, one integration test driving repo_root/has_uncommitted_changes against a real temporary git repository as a belt-and-braces check.

Full worklist: triage worklist.md (rollout Stage A artefact); dataset SHA b850e2f.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions