Claude Code Plugins

Community-maintained marketplace

Feedback

Test quality validation through mutation testing, assessing test suite effectiveness by introducing code mutations and measuring kill rate. Use when evaluating test quality, identifying weak tests, or proving tests actually catch bugs.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name mutation-testing
description Test quality validation through mutation testing, assessing test suite effectiveness by introducing code mutations and measuring kill rate. Use when evaluating test quality, identifying weak tests, or proving tests actually catch bugs.
version 1.0.0
category testing-methodologies
tags mutation-testing, test-quality, mutation-score, stryker, test-effectiveness
difficulty advanced
estimated_time 60 minutes
author agentic-qe

Mutation Testing

Core Principle

Tests test code. But who tests the tests?

Mutation testing validates test quality by introducing small code changes (mutations) and verifying tests catch them. High mutation score = effective tests.

What is Mutation Testing?

Process:

  1. Mutate code (change + to -, < to <=, remove if statements)
  2. Run tests against mutated code
  3. If tests fail → Mutation "killed" ✅ (good)
  4. If tests pass → Mutation "survived" ❌ (weak tests)

Mutation Score = Killed / (Killed + Survived)

Example:

// Original code
function isAdult(age) {
  return age >= 18; // ← Mutation: Change >= to >
}

// Test
test('18 is adult', () => {
  expect(isAdult(18)).toBe(true); // Catches mutation!
});

If test was weak:

test('19 is adult', () => {
  expect(isAdult(19)).toBe(true); // Doesn't catch >= vs >
});
// Mutation survives → Test needs improvement

Mutation Operators

Arithmetic: + → -, * → / Relational: < → <=, == → != Logical: && → ||, ! removed Conditional: if (x) → if (true), if (x) → if (false) Statement: Remove return, remove function call

Using Stryker

Install:

npm install --save-dev @stryker-mutator/core @stryker-mutator/jest-runner
npx stryker init

Configuration:

// stryker.conf.json
{
  "packageManager": "npm",
  "reporters": ["html", "clear-text", "progress"],
  "testRunner": "jest",
  "coverageAnalysis": "perTest",
  "mutate": [
    "src/**/*.ts",
    "!src/**/*.spec.ts"
  ],
  "thresholds": {
    "high": 90,
    "low": 70,
    "break": 60
  }
}

Run:

npx stryker run

Output:

Mutation Score: 87.3%
Killed: 124
Survived: 18
No Coverage: 3
Timeout: 1

With Agents

// qe-test-generator uses mutation testing
const mutationAnalysis = await agent.analyzeMutations({
  targetFile: 'src/payment.ts',
  generateMissingTests: true
});

// Returns:
// {
//   mutationScore: 0.65,
//   survivedMutations: [
//     { line: 45, operator: '>=', mutant: '>', killedBy: null }
//   ],
//   generatedTests: [
//     'test for boundary at line 45'
//   ]
// }

Remember

High code coverage ≠ good tests

  • 100% coverage but weak assertions = useless
  • Mutation testing proves tests work

With Agents: Mutation testing handler automatically runs mutations, identifies weak tests, and generates missing test cases to kill surviving mutations.