mutation-testing

Expert knowledge for mutation testing - validating that your tests actually catch bugs by introducing deliberate code mutations.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "mutation-testing" with this command: npx skills add secondsky/claude-skills/secondsky-claude-skills-mutation-testing

Mutation Testing

Expert knowledge for mutation testing - validating that your tests actually catch bugs by introducing deliberate code mutations.

Core Concept

  • Mutants: Small code changes introduced automatically

  • Killed: Test fails with mutation (good - test caught the bug)

  • Survived: Test passes with mutation (bad - weak test)

  • Score: Percentage of mutants killed (aim for 80%+)

TypeScript/JavaScript (Stryker)

Vitest Runner

Installation

Using Bun

bun add -d @stryker-mutator/core @stryker-mutator/vitest-runner

Using npm

npm install -D @stryker-mutator/core @stryker-mutator/vitest-runner

Configuration

// stryker.config.mjs export default { packageManager: 'bun', reporters: ['html', 'clear-text', 'progress'], testRunner: 'vitest', coverageAnalysis: 'perTest', mutate: ['src//*.ts', '!src//*.test.ts'], thresholds: { high: 80, low: 60, break: 60 }, incremental: true, }

Bun Native Runner (bun test )

Use when projects use bun test directly (not Vitest).

Requirements

  • Bun >= 1.3.7 (needs TestReporter WebSocket events from Bun PR #25986)

  • @stryker-mutator/core ^9.0.0

Installation

bun add -D @hughescr/stryker-bun-runner @stryker-mutator/core

Configuration

// stryker.conf.mjs export default { testRunner: 'bun', coverageAnalysis: 'perTest', mutate: ['src//*.ts', '!src//*.test.ts'], thresholds: { high: 80, low: 60, break: 60 }, incremental: true, bun: { inspectorTimeout: 5000, // WebSocket Inspector connection timeout (ms) // bunPath: '/path/to/bun', // only if custom Bun install // timeout: 30000, // test timeout (ms) // env: { DEBUG: 'true' }, // bunArgs: ['--bail'], }, }

Key Behaviors

  • Sequential execution: Runs tests with --concurrency=1 for accurate per-test coverage. Slower than parallel but required for correct test-to-mutant correlation.

  • Concurrent test patching: Automatically patches describe.concurrent() , test.concurrent() , it.concurrent() to run sequentially during mutation testing — no code changes needed.

  • Inspector Protocol: Uses Bun's WebSocket Inspector API to discover tests and correlate coverage.

Running Stryker

Run mutation testing

bunx stryker run

Incremental mode (only changed files)

bunx stryker run --incremental

Specific files

bunx stryker run --mutate "src/utils/**/*.ts"

Open HTML report

open reports/mutation/html/index.html

Example: Weak Test

// Source code function calculateDiscount(price: number, percentage: number): number { return price - (price * percentage / 100) }

// ❌ WEAK: Test passes even if we mutate calculation test('applies discount', () => { expect(calculateDiscount(100, 10)).toBeDefined() // Too weak! })

// ✅ STRONG: Test catches mutation test('applies discount correctly', () => { expect(calculateDiscount(100, 10)).toBe(90) expect(calculateDiscount(100, 20)).toBe(80) expect(calculateDiscount(50, 10)).toBe(45) })

Python (mutmut)

Installation

uv add --dev mutmut

Running mutmut

Run mutation testing

uv run mutmut run

Show results

uv run mutmut results

Show specific mutant

uv run mutmut show 1

Generate HTML report

uv run mutmut html open html/index.html

Common Mutation Types

// Arithmetic Operator // Original: a + b → a - b, a * b, a / b

// Relational Operator // Original: a > b → a >= b, a < b, a <= b

// Logical Operator // Original: a && b → a || b

// Boolean Literal // Original: true → false

Mutation Score Targets

Score Quality Action

90%+ Excellent Maintain quality

80-89% Good Small improvements

70-79% Acceptable Focus on weak areas

< 60% Poor Major improvements needed

Improving Weak Tests

Pattern: Insufficient Assertions

// Before: Mutation survives test('calculates sum', () => { expect(sum([1, 2, 3])).toBeGreaterThan(0) // Weak! })

// After: Mutation killed test('calculates sum correctly', () => { expect(sum([1, 2, 3])).toBe(6) expect(sum([0, 0, 0])).toBe(0) expect(sum([])).toBe(0) })

Pattern: Boundary Conditions

// After: Tests boundaries test('validates age boundaries', () => { expect(isValidAge(18)).toBe(true) // Min valid expect(isValidAge(17)).toBe(false) // Just below expect(isValidAge(100)).toBe(true) // Max valid expect(isValidAge(101)).toBe(false) // Just above })

Best Practices

  • Start with core business logic modules

  • Ensure 80%+ coverage before mutation testing

  • Run incrementally (only changed files)

  • Focus on important files first

  • Don't expect 100% mutation score (equivalent mutants exist)

Workflow

1. Ensure good coverage first

bun test --coverage

Target: 80%+ coverage

2. Run mutation testing

bunx stryker run

3. Check report

open reports/mutation/html/index.html

4. Fix survived mutants

5. Re-run incrementally

bunx stryker run --incremental

or: npx stryker run --incremental

See Also

  • vitest-testing

  • Unit testing framework

  • test-quality-analysis

  • Detecting test smells

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

code-review

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

claude-code-bash-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

chrome-devtools

No summary provided by upstream source.

Repository SourceNeeds Review