|

Mutation Testing: Are Your Tests Actually Catching Bugs? (Stryker Guide)

Your tests pass. Code coverage is 90%. But do your tests actually catch bugs? Mutation testing answers this by injecting bugs into your code and checking if tests detect them.

🎭 Want to master this with real projects? Join the Playwright Automation Mastery course at The Testing Academy.

Contents

How Mutation Testing Works

Original code:    if (price > 100) { applyDiscount(); }
Mutant 1:         if (price >= 100) { applyDiscount(); }  // Changed > to >=
Mutant 2:         if (price < 100) { applyDiscount(); }   // Changed > to <
Mutant 3:         if (price > 100) { /* removed */ }      // Removed function call

If your tests PASS with the mutant = SURVIVED = your tests are weak
If your tests FAIL with the mutant = KILLED = your tests caught the bug

Mutation Score

Mutation Score = Killed Mutants / Total Mutants

  • 90%+ = Excellent — tests catch most injected bugs
  • 70-90% = Good — some gaps to address
  • Below 70% = Weak — tests give false confidence

Setting Up Stryker (JavaScript/TypeScript)

npm install -D @stryker-mutator/core @stryker-mutator/typescript-checker
npx stryker init
// stryker.config.json
{
  "mutate": ["src/**/*.ts", "!src/**/*.spec.ts"],
  "testRunner": "jest",
  "checkers": ["typescript"],
  "reporters": ["html", "clear-text"],
  "thresholds": {
    "high": 80,
    "low": 60,
    "break": 50
  }
}

🚀 Level Up Your Playwright

From locators to CI pipelines — build a production-grade Playwright + TypeScript framework step by step.

Common Mutation Types

MutationExampleWhat It Tests
Conditional boundary> becomes >=Boundary value assertions
Negate conditional== becomes !=Logic correctness
Remove callFunction call deletedSide effect verification
Return valuereturn true becomes falseReturn value assertions
Arithmetic+ becomes –Calculation assertions
String literal“hello” becomes “”String content checks

Interpreting Results

# Run mutation testing
npx stryker run

# Output:
# Mutant #1 (ConditionalBoundary): KILLED by test "should reject order over limit"
# Mutant #2 (RemoveCall):          SURVIVED - no test detected removal of sendEmail()
# Mutant #3 (BooleanLiteral):      KILLED by test "should return false for invalid input"
#
# Mutation score: 78% (36/46 mutants killed)

Mutation Testing vs Code Coverage

MetricWhat It MeasuresLimitation
Code coverageLines executed by testsExecuted != verified. No assertions = 100% coverage, 0% confidence
Mutation scoreBugs actually caught by testsSlow to run. Use on critical modules, not entire codebase

🎓 Master Playwright End to End

Join hundreds of SDETs building real automation frameworks. Lifetime access, hands-on projects, and a job-ready portfolio.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.