Skip to content
AI and Code

AI Test Quality: Mutation Testing and Evals

10 min read

Test coverage measures whether code ran, not whether anything checked its behaviour, so a high-coverage AI-generated suite can verify almost nothing. Mutation testing is the sensor that catches this: it changes the code and checks whether a test fails. For correctness that is hard to assert deterministically, such as generated tests and policy logic, semantic evals add a probabilistic, model-based check. Together they turn test quality from an assumption into a measurement.

  • Coverage is necessary but not sufficient. A green, high-coverage suite can still test nothing.
  • Mutation testing (Stryker.NET on .NET) reveals weak or missing assertions.
  • Semantic evals handle correctness that deterministic tests cannot express. Run them downstream of the cheap checks.

Our Claude Code development service builds test-quality sensors into every engagement.

This guide goes deep on one specific sensor from our maintainability sensors guide: the one that checks whether your tests actually test anything. It matters more in the age of coding agents, because agents are very good at producing tests that look thorough and are not.

Why does test coverage lie about AI-written tests?

Coverage tells you a line of code executed during a test. It does not tell you that any assertion checked what that line did. The two are easy to confuse, and the gap between them is where false confidence lives.

AI coding agents make the gap worse. Asked to add tests, an agent will happily produce a suite that exercises every branch and asserts almost nothing meaningful, or asserts something trivially true. The coverage number climbs, the suite goes green, and a reviewer glancing at the percentage concludes the code is well tested. It is not.

This is not a hypothetical. Birgitta Böckeler’s 27 May 2026 article on maintainability sensors describes finding high-coverage mappers whose assertions did not actually verify the mapping. The coverage was real. The testing was not.

What is mutation testing, and how does it catch the gap?

Mutation testing measures whether your tests detect changes to the code, which is the thing coverage cannot see. It works by deliberately introducing small faults and checking whether the suite notices.

The mechanism is simple:

  • Make a small change to the code under test, for example flip a > to a >=, or delete a statement.
  • Rerun the affected tests.
  • If a test fails, it “killed” the mutant. Good: a test was actually checking that behaviour.
  • If no test fails, the mutant “survived”. That code ran during testing but nothing asserted against it.

The output is a list of surviving mutants, and that list is precise and actionable. Each survivor names a specific behaviour your suite claims to cover but does not. Unlike a coverage percentage, it points at exactly what to fix.

How do you run mutation testing on .NET without it being slow?

Run it incrementally and place it in the post-integration tier, not on every commit. Mutation testing is more expensive than ordinary test runs because it reruns tests many times, so the cost has to be managed rather than ignored.

On .NET we use Stryker.NET. The practical configuration:

  • Incremental runs so only changed code is mutated, which keeps each run proportionate to the size of the change.
  • Post-integration or scheduled cadence, alongside other expensive sensors, rather than in the tight commit loop.
  • A target on the surviving-mutant list, not on a single headline score, so the team fixes real gaps instead of gaming a number.

JavaScript and TypeScript teams have an equivalent in StrykerJS, so the same discipline carries to the React side of a stack. The sequencing principle from the harness engineering guide applies: cheap checks every commit, expensive checks on a cadence.

What about correctness beyond unit tests?

Some correctness questions cannot be expressed as a deterministic assertion at all. For these, a semantic eval adds a probabilistic, often model-based check. The Generative Programmer’s 29 May 2026 article on the missing quality layer names this as one of the controls teams most often lack.

Semantic evals are useful in three places in particular:

  • Generated tests, to judge whether the assertions are meaningful, not just present.
  • Policy and business logic, where correctness depends on intent that is awkward to encode in fixtures.
  • Tool-using workflows, where the agent chains calls and the right answer is a behaviour, not a value.

Frameworks such as DeepEval provide structure for writing these evaluations. Research techniques like semantic entropy, which flags unreliable model output by measuring disagreement across sampled responses, point at where a generated answer is least trustworthy. The detail matters less than the role: an eval is a judgement-based check for correctness that deterministic tests cannot reach.

When is a semantic eval worth the cost?

Reach for a semantic eval only when a deterministic check cannot answer the question, and always run it downstream of the cheap checks. Evals are slower, cost tokens, and are non-deterministic, so they earn their place only where judgement is genuinely required.

The heuristic is the same one that governs inferential sensors generally: a control that produces the same answer twice should be a computational check instead. If a semantic eval keeps returning a stable verdict, promote it to a deterministic assertion and save the cost. Keep evals for the questions that really do need interpretation.

How do you combine coverage, mutation testing, and evals into a quality gate?

Layer the three by cost and certainty, so the cheapest, most certain checks gate first and the expensive, probabilistic ones run last.

A workable gate for a .NET and React system:

  • Every commit: the test suite plus coverage, as a fast baseline. Coverage stays useful as a floor, just not as proof of quality.
  • Post-integration: Stryker.NET mutation testing, incremental, to expose weak assertions.
  • Scheduled or targeted: semantic evals on generated tests, policy logic, and high-risk workflows, grounded in the deterministic results above.

The combination is what matters. Coverage shows reach, mutation testing shows whether the reach is real, and evals cover the correctness that neither can express. No single layer is sufficient on its own.

Why should a CTO care about AI test quality?

Because a high-coverage AI-generated test suite can quietly overstate how well a system is tested, and that is a delivery and assurance risk. Defects ship behind a reassuring number, and the evidence trail says quality is higher than it is.

This is sharper now that AI authors most of the code. Our Q1 2026 AI Velocity Report records 84% of code as AI-authored. At that ratio, taking test suites at face value is a real exposure. Mutation testing and targeted evals turn test quality from an assumption into a measurement, which is what both code review and regulatory assurance depend on. We make the wider case for not trusting unsupervised AI output in our blog post on why we do not let AI ship code unsupervised.

How does Talk Think Do test AI-written code?

We treat test quality as something to measure, not assume, and the sensor layer reflects that:

  • Stryker.NET mutation testing runs as a post-integration sensor, so weak assertions surface before release.
  • Coverage remains a baseline floor, never the headline quality signal.
  • Every AI-authored change passes senior engineer review and ISTQB-qualified QA validation, inside our ISO 27001-certified framework.

The result is that high AI authorship and high test quality coexist, because the tests themselves are tested. For the full sensor picture this fits into, read the maintainability sensors guide and the harness engineering guide.

To review the test quality of an AI-augmented codebase, book a free consultation.

Frequently asked questions

Why does test coverage lie about AI-written tests?
Coverage measures whether a line of code ran during a test, not whether an assertion checked its behaviour. AI coding agents readily produce high-coverage suites with weak or missing assertions, so the suite is green and the number is high while the tests verify almost nothing. Coverage is necessary but not sufficient. Mutation testing is what reveals the gap.
What is mutation testing?
Mutation testing deliberately introduces small changes to the code under test, such as flipping a comparison or removing a line, then reruns the tests. If a test fails, it caught the change. If no test fails, the mutant survived, which means a test executed that code but never actually tested it. The surviving mutants are a precise list of behaviours your suite claims to cover but does not.
What tool runs mutation testing on .NET?
Stryker.NET is the standard mutation testing tool for .NET. It mutates the code, reruns the affected tests, and reports surviving mutants. Incremental runs keep it affordable by only testing what changed, so it fits in the post-integration or scheduled tier rather than running on every commit. JavaScript and TypeScript have an equivalent in StrykerJS.
What is a semantic eval, and when do you need one?
A semantic eval is a probabilistic, often model-based check of correctness that goes beyond syntax and pass or fail tests. It is useful where behaviour is hard to assert deterministically, such as generated tests, policy logic, and tool-using workflows. Run it downstream of deterministic checks. If a question can be answered the same way twice by a computational tool, use the tool instead.
Does mutation testing replace code coverage?
No. Use them together. Coverage tells you which code your tests reach; mutation testing tells you whether those tests actually verify behaviour. Coverage is the cheap, every-commit signal. Mutation testing is the slower, post-integration signal that catches the false confidence coverage alone can create, especially in AI-generated suites.
Why should a CTO care about AI test quality?
Because a high-coverage AI-generated test suite can give false assurance that a system is well tested when it is not. That is a delivery and regulatory risk: defects ship, and the evidence trail overstates quality. Mutation testing and targeted semantic evals turn test quality from an assumption into something measured, which is what review and assurance both depend on.

Ready to transform your software?

Let's talk about your project. Contact us for a free consultation and see how we can deliver a business-critical solution at startup speed.