Retour aux articles
engineering3 min de lecture

Stop demanding 80% test coverage. Demand it never goes down.

Why a coverage ratchet beats a hard coverage gate on a real codebase

Rob Vasquez·

Every engineering org I have seen has the same number written down somewhere: 80% test coverage. And almost none of them enforce it, because the day someone tries, one of two things happens. Either every merge gets blocked on a codebase that sits at 25%, and the gate is turned off within a week. Or teams start writing coverage theater: tests that execute lines without asserting anything, just to feed the meter.

The policy is not wrong because 80% is a bad target. It is wrong because a hard gate on an aspirational number punishes the present for the sins of the past. The engineer shipping a well-tested feature today did not create the untested legacy module from 2023, but the gate treats them as if they did.

On my platform monorepo, which runs 20+ apps against a shared Express API, I replaced the hard gate with a ratchet. One committed file holds a single number: the coverage floor, currently 25%, seeded from the last honestly measured figure. CI fails a pull request only if measured global coverage drops below that floor. That is the whole rule.

Then the second half, which is what makes it a ratchet and not just a low bar: when measured coverage clears the floor by a comfortable margin, the workflow nudges you to raise the number. The floor climbs, one incremental commit at a time, and there is a written rule that it never gets lowered without a documented regression reason. The 80% figure still exists in the docs, but as the direction of travel, not a merge gate.

What changed in practice:

Merges stopped being hostage to history. A one-line bug fix in a mature module no longer fails CI because an unrelated legacy directory has no tests. The gate only asks: did you make it worse?

Coverage started actually going up. When the gate is impossible, people route around it and the number means nothing. When the gate is "do not regress," the cheapest way to pass is to test the code you just wrote, which is exactly the code most worth testing.

The number became trustworthy. Nobody games a floor they comfortably clear. The measured figure now reflects real tests, because there is no pressure to inflate it.

Regressions became visible events. Lowering the floor requires a commit with a written reason. That turns a silent quality slide into a reviewed decision with a name on it.

The general principle goes past testing. Any quality metric on a codebase with history, whether type coverage, lint debt, bundle size, or accessibility violations, works better as a ratchet than a threshold. Absolute standards are for greenfield. Monotonic improvement is for the real systems the rest of us maintain.

If your quality gates are so strict that everyone bypasses them, you do not have quality gates. You have a document. A floor that actually holds beats a target that everyone ignores.

EngineeringLeadershipPlatformEngineeringTestingCI

Besoin d'un chemin pratique vers une livraison assistée par l'IA ?

Commencez par un audit de préparation à l'IA à prix fixe et repartez avec une feuille de route concrète.

Voir l'audit de préparation à l'IA