Day 10 of 60 · Unit, integration, contract

Code coverage (with caveats)

A coverage number is signal, not target. Set a hard gate and the team writes vacuous tests; surface it in PRs and it points reviewers at the soft spots.

ProblemUntested code paths are invisible until they ship a bug.

How it works

Instruments tests to record which lines/branches executed. Surface coverage in PRs, but never set hard gates; it inverts the incentive.

What it catches

Surfaces untested areas for review. Does not catch bugs directly. Pairs with mutation testing to avoid Goodhart's trap.

Tools

Coverage.py · OSS Istanbul / nyc · OSS Codecov · Hybrid

Verdict by project size

Small
Opt
Medium
Rec
Large
Rec
Extra-large
Rec

Cost

Project size Setup Maint / mo Tool / mo CI / run
Small <10k LOC 2h 0.5h $0 +0.5m
Medium 10–100k LOC 4h 2h $0 +1m
Large 100k–1M LOC 2d 8h $200 +3m
Extra-large >1M LOC 5d 25h $1k +8m
Setup = engineer-days to first useful run · Maint = engineer-hours / month at steady state · Tool = out-of-pocket $ / month · CI = minutes added (or saved) per pipeline run

Lifecycle & ownership

When in lifecycle
Code Test
Per pull request · Runs in CI on every PR; gates merge.
Who owns it
Developer
Authoring + the inner loop
Collaborates with: QA / Test Engineer

Reference implementations

Quick check

Why are hard coverage gates considered an anti-pattern?

One question. Pick the best answer. Your streak is saved locally on this device.

Save the lesson

Download SVG ↓

Screenshot for a 1:1, drop it in Slack, or download the SVG.

thinkbridge THE VALIDATION ATLAS DAY 10 OF 60 UNIT, INTEGRATION, CONTRACT Code coverage (withcaveats) A coverage number is signal, not target. Set a hard gate andthe team writes vacuous tests; surface it in PRs and itpoints reviewers at the soft spots. FIVE-MINUTE LESSON · ONE QUICK-CHECK QUESTION There’s a new way there
All 60 days →