Your tests are lying to you: A practical introduction to mutation testing

A presentation at Clermont’ech - API Hour #72 in June 2026 in Clermont-Ferrand, France by Romain Rochegude

Slide 1

Slide 1

Your Tests Are Lying to You: A Practical Introduction to Mutation Testing

Slide 2

Slide 2

Romain Rochegude Software Architect IT Technical Manager RoRoche

Slide 3

Slide 3

“Program testing can be used to show the presence of bugs, but never to show their absence!” — Edsger W. Dijkstra

Slide 4

Slide 4

Who here believes they have good test coverage? 70%? 80%? 90%?

Slide 5

Slide 5

And now, who is confident that their tests actually catch real bugs?

Slide 6

Slide 6

The False Sense of Safety ✅ Green tests ✅ CI pipeline is fine ✅ High coverage 🐛 And yet… bugs still reach production

Slide 7

Slide 7

Our tests pass… but do they really test anything?

Slide 8

Slide 8

What if, instead of testing our code, we started testing our tests?

Slide 9

Slide 9

🧯 The Problem: What Coverage Doesn’t Tell You Coverage ≠ Test Quality Coverage measures: executed lines not validated behavior A test suite can look “good” even if: assertions are too weak edge cases are missing important conditions are never challenged

Slide 10

Slide 10

Coverage answers “what was executed?” It does not answer “what is actually protected?” 👉 Code coverage is comforting — but it proves nothing.

Slide 11

Slide 11

🤔 The Real Question “If I break the code… will my tests notice?”

Slide 12

Slide 12

✅ The Solution: Mutation Testing What Is Mutation Testing? Mutation testing is about: Intentionally breaking the production code to check whether the tests fail Or more bluntly: “If your tests don’t fail, they’re useless.”

Slide 13

Slide 13

🔬 How It Works 1. 🧬 Inject mutants into the production code conditional changes boolean inversions arithmetic operator changes 2. ▶️ Re-run the unit tests 3. 📊 Analyze the results ❌ Mutant killed → ✅ test is effective ✅ Mutant survives → 🚨 test is weak or missing 👉 We are no longer verifying code execution, but behavior protection.

Slide 14

Slide 14

📈 The Mutation Score Mutation score = percentage of mutants killed by the test suite This gives us a new signal: Not “did tests run?” But “did tests react?” A higher mutation score means more meaningful tests.

Slide 15

Slide 15

🖥️ Live Demo — Making Tests Fail on Purpose Goal: prove that passing tests do NOT necessarily mean protected code

Slide 16

Slide 16

💡 Concrete Benefits Why Mutation Testing Is Powerful ✅ Evaluate test robustness ✅ Identify missing or insufficient tests ✅ Improve the overall quality of the test suite ✅ Go beyond raw code coverage Coverage tells you where to look. Mutation testing tells you what to fix.

Slide 17

Slide 17

🎁 Positive Side Effects Better test design Cleaner, simpler production code Less dead or defensive logic More valuable technical discussions 💬 “Why does this mutant survive?” ➡️ A great question about design, intent, and architecture.

Slide 18

Slide 18

⚠️ Limitations The Main Drawback ⏱️ Execution time Tests are executed many times Computationally expensive Not suitable for all code, all the time Mutation testing forces trade-offs.

Slide 19

Slide 19

🧠 Use It Smartly ✅ Apply mutation testing on: Critical business logic Core domain rules Algorithms ✅ Run it: Periodically On dedicated CI jobs During refactoring or hardening phases You don’t need a perfect score. An imperfect but understood mutation score is far better than perfect but misleading coverage.

Slide 20

Slide 20

🏁 Conclusion ❌ Testing code execution is not enough ✅ We must test the effectiveness of our tests Mutation testing doesn’t replace your tests. It reveals whether they actually matter.

Slide 21

Slide 21

🚀 Call to Action Key takeaways: Coverage reassures Mutation testing challenges Quality improves when we embrace discomfort “Your tests pass? Good. Now let’s try to make them fail.”

Slide 22

Slide 22

Thank you Powered by