Analyzes surviving mutants from mutation testing to identify why tests failed to detect them. Takes repository code, test suite, and mutation testing results as input. Identifies root causes including insufficient coverage, equivalent mutants, weak assertions, and missed edge cases. Automatically generates actionable test improvements and new test cases. Use when analyzing mutation testing results, improving test suite effectiveness, investigating low mutation scores, generating tests to kill surviving mutants, or enhancing test quality based on mutation analysis.
94
92%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
This skill systematically analyzes surviving mutants from mutation testing to understand test suite weaknesses and automatically generate improvements. It identifies why mutants survived, categorizes root causes, and produces actionable test enhancements to increase mutation detection rates.
Gather required inputs and verify completeness:
Required Inputs:
Mutation Result Formats:
Validation checklist:
Parse mutation results to identify all surviving mutants:
Extract for each mutant:
Focus on survived mutants: Filter out killed mutants and focus analysis on survivors that indicate test weaknesses.
Analyze each surviving mutant to determine why it survived:
Indicators:
Analysis:
Example:
// Original
public int calculate(int x) {
if (x > 0) {
return x * 2; // Line 3: Covered
}
return 0; // Line 5: NOT covered
}
// Mutant: Line 5 changed to "return 1;"
// Survives because no test calls calculate() with x <= 0Indicators:
Analysis:
Example:
# Original
result = x * 1
# Mutant: changed to "result = x"
# Equivalent: multiplying by 1 has no effectIndicators:
Analysis:
Example:
// Test
test('calculate returns a number', () => {
const result = calculate(5);
expect(typeof result).toBe('number'); // Weak: doesn't check value
});
// Mutant: "return x * 2" → "return x * 3"
// Survives because test only checks type, not valueIndicators:
Analysis:
Example:
// Original
public int divide(int a, int b) {
return a / b;
}
// Mutant: added "if (b == 0) return 0;"
// Survives because no test checks division by zeroIndicators:
Analysis:
Indicators:
Analysis:
For each surviving mutant, determine the appropriate test enhancement:
Strategy 1: Add Missing Test Cases
Strategy 2: Strengthen Assertions
Strategy 3: Add Edge Case Tests
Strategy 4: Mark as Equivalent
Strategy 5: Add Integration Tests
Generate concrete test code to kill surviving mutants:
Test Generation Process:
Example Generated Test:
def test_calculate_with_negative_input():
"""
Test to kill mutant #42: calculate() with x <= 0
Mutant changed 'return 0' to 'return 1' on line 5
"""
result = calculate(-5)
assert result == 0, "calculate() should return 0 for negative input"
result = calculate(0)
assert result == 0, "calculate() should return 0 for zero input"Create comprehensive analysis report using template in assets/mutation_analysis_report.md:
Report Sections:
Common mutation operators and their implications:
Arithmetic Operators:
+ ↔ -, * ↔ /, % ↔ *Relational Operators:
> ↔ >=, < ↔ <=, == ↔ !=Logical Operators:
&& ↔ ||, ! insertion/removalConditional Boundaries:
< ↔ <=, > ↔ >=Return Values:
Statement Deletion:
For detailed mutation operator catalog, see references/mutation_operators.md.
Parse PIT XML reports:
# Run PIT
mvn org.pitest:pitest-maven:mutationCoverage
# Report location
target/pit-reports/YYYYMMDDHHMI/mutations.xmlParse Stryker JSON reports:
# Run Stryker
npx stryker run
# Report location
reports/mutation/mutation.jsonParse mutmut results:
# Run mutmut
mutmut run
# Show results
mutmut results
mutmut show [mutant-id]For tool-specific parsing guidance, see references/tool_integration.md.
Example 1: Insufficient Coverage
Surviving mutant:
// Line 15: return defaultValue; → return null;Analysis: No test calls this method with conditions triggering line 15.
Generated test:
@Test
public void testGetValueWithMissingKey() {
// Kills mutant on line 15
String result = config.getValue("nonexistent");
assertEquals("default", result);
}Example 2: Weak Assertion
Surviving mutant:
# Line 8: return items[:5] → return items[:4]Analysis: Test only checks len(result) > 0, not exact length.
Enhanced test:
def test_get_top_items_returns_five():
# Kills mutant on line 8
items = create_test_items(10)
result = get_top_items(items)
assert len(result) == 5, "Should return exactly 5 items"Example 3: Equivalent Mutant
Surviving mutant:
// Original: if (x > 0 && x < 100)
// Mutant: if (0 < x && 100 > x)Analysis: Logically equivalent, no behavioral difference.
Action: Mark as equivalent in mutation config, no test needed.
Prioritize mutants:
Test quality over quantity:
Iterative improvement:
Document equivalent mutants:
For detailed information on specific topics:
references/mutation_operators.mdreferences/tool_integration.mdreferences/test_patterns.md0f00a4f
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.