running-mutation-tests

Execute mutation testing to evaluate test suite effectiveness. Use when performing specialized testing. Trigger with phrases like "run mutation tests", "test the tests", or "validate test effectiveness".

claude-codecodexopenclaw
6 Tools
mutation-test-runner Plugin
testing Category

Allowed Tools

ReadWriteEditGrepGlobBash(test:mutation-*)

Provided by Plugin

mutation-test-runner

Mutation testing to validate test quality by introducing code changes and verifying tests catch them

testing v1.0.0
View Plugin

Installation

This skill is included in the mutation-test-runner plugin:

/plugin install mutation-test-runner@claude-code-plugins-plus

Click to copy

Instructions

Mutation Test Runner

Overview

Execute mutation testing to evaluate the effectiveness of a test suite by systematically introducing small code changes (mutants) and checking whether existing tests detect them. A killed mutant means the tests caught the change; a surviving mutant reveals a testing gap.

Prerequisites

  • Mutation testing framework installed (Stryker, mutmut, PITest, or go-mutesting)
  • Existing test suite with reasonable pass rate (all tests must pass before mutation testing)
  • Source code with functions and logic suitable for mutation (conditionals, arithmetic, return values)
  • Sufficient CI resources (mutation testing runs the test suite once per mutant -- CPU-intensive)
  • Configuration file for the mutation tool specifying target files and test commands

Instructions

  1. Verify the existing test suite passes completely:
  • Run the full test suite and confirm 100% pass rate.
  • Fix any failing or skipped tests before proceeding.
  • Mutation testing is meaningless if the baseline tests are broken.
  1. Configure the mutation testing tool:
  • Stryker: Create stryker.config.mjs with mutate patterns, test runner, and thresholds.
  • mutmut: Configure setup.cfg or pyproject.toml with [mutmut] section.
  • PITest: Add Maven/Gradle plugin with target classes and test configurations.
  1. Select target files for mutation:
  • Focus on business logic modules (not configuration, constants, or type definitions).
  • Exclude auto-generated code, third-party wrappers, and test utilities.
  • Start with a small scope (one module) to validate setup before expanding.
  1. Run the mutation testing suite:
  • Execute npx stryker run, mutmut run, or mvn pitest:mutationCoverage.
  • Monitor progress -- expect long execution times (10-100x normal test runtime).
  • Use incremental mode if available to skip already-tested mutants.
  1. Analyze the mutation report:
  • Killed mutants: Tests detected the change -- indicates strong test coverage.
  • Survived mutants: Tests did not catch the change -- indicates a testing gap.
  • Timed out mutants: Mutation caused an infinite loop -- generally acceptable.
  • No coverage mutants: The mutated code is not exercised by any test.
  1. For each surviving mutant, determine the appropriate action:
  • Write a new test that specifically catches the mutation.
  • Or determine the mutation is equivalent (functionally identical to original) and mark as ignored.
  1. Set mutation score thresholds (recommended: 80% kill rate) and integrate into CI as a quality gate.

Output

  • Mutation testing report (HTML or JSON) with killed/survived/timed-out counts
  • Mutation score percentage (killed / total non-equivalent mutants)
  • Surviving mutant inventory with file, line, mutation type, and suggested test
  • New test cases written to kill surviving mutants
  • CI configuration with mutation score threshold enforcement

Error Handling

Error Cause Solution
Mutation run takes hours Too many files in scope or slow test suite Narrow mutate scope to critical modules; use --incremental mode; parallelize with --concurrency
All mutants survive Tests only check for truthiness, not specific values Strengthen assertions -- use toBe(42) instead of toBeTruthy(); add boundary checks
Equivalent mutant false positive Mutation produces functionally identical code (e.g., x >= 0 vs x > -1) Mark as equivalent in config; ignore in score calculation; document rationale
Out of memory during run Too many concurrent mutation workers Reduce --concurrency setting; increase Node.js --max-old-space-size; reduce shard size
Stryker "initial test run failed" Test suite does not pass cleanly before mutations begin Fix all failing tests first; ensure npm test exits 0; check test runner configuration

Examples

Stryker configuration for TypeScript project:


// stryker.config.mjs
export default {
  mutate: ['src/**/*.ts', '!src/**/*.d.ts', '!src/**/index.ts'],
  testRunner: 'jest',
  jest: { configFile: 'jest.config.ts' },
  reporters: ['html', 'clear-text', 'progress'],
  thresholds: { high: 80, low: 60, break: 50 },
  concurrency: 4,
  timeoutMS: 10000,  # 10000: 10 seconds in ms
};

Example surviving mutant and fix:


Mutant: src/utils/discount.ts:15 -- ConditionalExpression
  Original:  if (total > 100)
  Mutant:    if (total >= 100)
  Status:    SURVIVED

Fix -- add boundary test:
it('does not apply discount at exactly 100', () => {
  expect(calculateDiscount(100)).toBe(0);
});
it('applies discount above 100', () => {
  expect(calculateDiscount(101)).toBe(10.1);
});

mutmut for Python:


# Run mutation testing
mutmut run --paths-to-mutate=src/ --tests-dir=tests/

# View surviving mutants
mutmut results

# Inspect a specific mutant
mutmut show 42

Resources

  • Stryker Mutator: https://stryker-mutator.io/
  • mutmut (Python): https://github.com/boxed/mutmut
  • PITest (Java): https://pitest.org/
  • go-mutesting: https://github.com/zimmski/go-mutesting
  • Mutation testing theory: https://en.wikipedia.org/wiki/Mutation_testing

Ready to use mutation-test-runner?