Killed Mutant in Mutation Testing
A mutant is considered killed when the test suite detects the behavior introduced by the mutation, typically because at least one test fails. In mutation testing, a high proportion of killed mutants indicates that tests are detecting many small code changes.
Mutation testing evaluates test quality by making small, deliberate changes to production code called mutations. Each modified version is a mutant, and the original test suite is run against it.
A mutant is killed when at least one test fails because of the injected change. The failure shows that the test suite distinguishes the mutated behavior from the intended behavior.
If all tests pass against a mutant, the mutant survives. A surviving mutant can indicate that the tests do not cover the changed behavior, do not assert the relevant result, or that the mutation does not affect observable behavior.
For example, changing `>` to `>=` may create a mutant that changes behavior at a boundary value. If a test exercises that boundary and fails after the mutation, the mutant is killed. Mutation-testing tools such as PIT can automate mutation generation and execution for Java projects.
Key points
- A killed mutant causes at least one test to fail.
- The failing test demonstrates that the mutation was detected.
- A surviving mutant passes the existing test suite.
- Killed mutants are evidence about the fault-detection ability of tests, not simply code coverage.
- Mutation testing deliberately introduces small code changes to evaluate tests.
Interview questions
How does a mutant become killed?
A mutation-testing tool changes a small part of the production code and runs the relevant tests. If at least one test fails as a consequence of that change, the mutant is marked as killed. The important part is that the failure is caused by the changed behavior, rather than by an unrelated test or environmental problem.
What is a killed mutant in mutation testing?
A killed mutant is a mutated version of the code for which at least one test fails. The failure means the test suite detected the behavior introduced by the mutation. This is useful evidence that the tests check the affected behavior rather than merely executing the code. The opposite case is a surviving mutant, where the tests continue to pass.
What does a surviving mutant tell you about a test suite?
A surviving mutant means the existing tests did not detect the particular code change. This may reveal missing assertions, inadequate input cases, insufficient boundary testing, or code whose changed behavior is not observable. It does not automatically prove that the production code or the test suite is wrong, because some mutations can be equivalent to the original behavior.
How is a killed mutant different from code coverage?
Code coverage tells you whether particular code was executed by tests, whereas mutation testing asks whether tests detect changes to that code. A line can have high coverage while its behavior is poorly asserted. For example, a test may execute a conditional branch without checking the result that would change when an operator is mutated. Therefore, mutation testing provides a different perspective on test effectiveness.
How would you investigate a surviving mutant in a Java backend project?
First, I would inspect the mutation and identify the behavior it changes. Then I would examine which tests execute the affected code and whether they assert the relevant outcome, especially around boundaries and error cases. If the behavior matters, I would add or strengthen a focused test and rerun mutation testing. If the mutation is behaviorally equivalent or irrelevant to the system's observable contract, I would consider whether it should be excluded or otherwise handled by the project's mutation-testing configuration.