Triage and Ignoring Mutants
Relevant source files
The following files were used as context for generating this wiki page:
Triage and ignoring mutants allows you to suppress specific code changes that a test suite cannot catch, often because the mutant is semantically equivalent to the original code. Mutineer provides tools to identify survivors, generate ignore entries, and migrate existing configurations as the project evolves.
Overview of Mutant Suppression
Suppression removes specific mutants from the mutation score denominator. This ensures that intentional or unkillable "equivalent mutants" do not fail CI gates. Mutineer supports three primary suppression methods:
- Inline Comments: You add
# mutineer:disable-lineto a source line to ignore all or specific operators. - Ignore List: You add mutant IDs to the
ignore:section of.mutineer.yml. - Triage Tooling: You use the
triagecommand to generate YAML-formatted ignore entries from JSON reports.
Sources: lib/mutineer/reporter.rb:149-152, test/equivalent_mutant_test.rb:23-27, skills/mutineer/SKILL.md:46-50
The Triage Process
The triage command extracts surviving mutant IDs from a JSON report and formats them for the .mutineer.yml configuration. It requires a surviving report file and a descriptive reason for suppression.
Triage Logic Flow
This diagram shows how the triage module processes a JSON report to generate ignore entries.
Sources: lib/mutineer/triage.rb:23-64
Triage Configuration Elements
| Element | Type | Description |
|---|---|---|
REPORT.json | Path | A JSON report generated by mutineer run --format json. |
--reason TEXT | String | A required explanation for why the mutants are being ignored. |
--id ID | String | A specific mutant ID to triage. Can be repeated. |
--all | Flag | Triages every survivor found in the provided report. |
Sources: lib/mutineer/triage.rb:11-13, lib/mutineer/triage.rb:45-48
Migrating Mutant IDs
Mutineer IDs historically excluded file paths, leading to collisions. Modern IDs include the project-relative file path for stability. The migrate command updates old-format IDs in .mutineer.yml to the current format.
Migration Logic
The migration system performs the following actions:
- ID Mapping: It identifies old-format IDs in the configuration.
- Validation: It checks if the old ID matches exactly one mutant in the current source code.
- Replacement: It replaces old IDs with new ones while preserving YAML comments and formatting.
- Collision Handling: If an old ID matches multiple new mutants (due to historical collisions), it warns the user to split the entry manually.
Sources: lib/mutineer/cli.rb:146-160, lib/mutineer/cli.rb:393-408, test/equivalent_mutant_test.rb:108-112
Migration Conflict Resolution
| Condition | Action |
|---|---|
| Old ID matches one new mutant | Automatic replacement in .mutineer.yml. |
| Old ID matches multiple mutants | Entry is left in place; CLI issues a warning to split by hand. |
| Old ID matches no mutants | Entry is left in place; CLI warns that the mutant no longer exists. |
Sources: lib/mutineer/cli.rb:149-159, lib/mutineer/cli.rb:411-424
Reporting Ignored Mutants
Ignored mutants are tracked separately from survivors and killed mutants. They are excluded from the denominator of the mutation score calculation.
Score Impact
The mutation score is calculated as killed / (killed + survived). Because ignored mutants are removed from this calculation, suppressing a survivor increases the overall score.
Identity and Citations in Reports
The JSON and HTML reports include an ignored section. Each entry provides:
- The stable mutant
id. - The
subject(qualified name of the method/class). - The
reasonprovided during triage or in the configuration file.
Sources: lib/mutineer/reporter.rb:316-335, lib/mutineer/reporter.rb:514-522
Summary
Triage and migration systems work together to manage the lifecycle of unkillable mutants. Triage provides the initial path for suppressing survivors identified in reports, while migration ensures that these suppressions remain valid as the project structure or Mutineer's ID formats change. Properly triaged mutants are excluded from the mutation score, allowing for a 100% score even when some mutations cannot be caught by tests.