← Workflows

阅读中文版本

Test Coverage Gap Analysis Workflow

Map coverage against change frequency and incident history, target the high-risk low-coverage quadrant first, and measure by gap closure.

beginner~30 mintest-strategycoveragerisk

Objective

Direct test-writing effort where risk lives: files that change often, carry incidents, and lack coverage, rather than chasing a global percentage.

Environment

  • Line or branch coverage reporting in CI
  • Git history available for change-frequency analysis
  • Incident or bug tracker with affected-file mapping

Steps

1. Join coverage with change frequency

Produce a scatter of every module: coverage percent against commits per month, identifying the high-churn low-coverage quadrant.

Expected state: A ranked list exists naming the files that change most while tested least.

2. Overlay incident history

Mark files that produced production incidents in the last two quarters, elevating them to the top of the gap queue.

Expected state: Incident-touched files with low coverage lead the priority list.

3. Classify the gaps by type

For top files, classify missing coverage: happy path, error handling, boundary values, or integration seams, since each needs different test styles.

Expected state: Each gap entry carries its type and the test approach planned.

4. Write tests gap-first, not percent-first

Close the top gaps with tests targeting the classified type, accepting that the global percentage moves little while risk drops much.

Expected state: Gap entries close with tests that fail against the old code when bugs are injected.

5. Institute change-triggered coverage gates

For files in the quadrant, require that new PRs either maintain or raise their file-level coverage, preventing re-entry into the gap.

Expected state: A PR touching a high-risk file with falling file coverage fails the check.

Expected outcome

Coverage effort concentrated on the churn-plus-incident-plus-untested quadrant, with per-file gates keeping gaps from reopening.

Verification

The next incident in a formerly gapped file is caught by a test added in this program; the quadrant population shrinks quarter over quarter.

A global percentage optimizes the wrong thing

Raising total coverage from 71 to 74 percent is easy: write tests for stable utility files. The risk lives in files that change weekly, broke production twice, and sit at 34 percent. Quadrant analysis points effort there.

quadrant (coverage x churn/month):
                 low churn      high churn
  high cover       61% of code     22%   (fine)
  low cover        14%   (later)   3%    (FIRST)

top of queue (incident-marked):
  checkout/promo.ts     34%  9 commits/mo  2 incidents
  api/webhooks.ts       21%  7 commits/mo  1 incident
  (utils/string.ts      88%  0 commits/mo      -- skip)

gap types: promo.ts -> boundary + error paths
  12 tests added; global % moved 71.2 -> 71.9 (risk: down)

Incident history beats any heuristic

Churn predicts future change, but an incident proves past damage: that file already hurt the business with insufficient tests. Files with both markers and low coverage are not a theoretical risk; they are a documented one awaiting its next occurrence.

File-level gates stop the revolving door

Global coverage cannot detect a risky file degrading while some utility file’s tests offset it numerically. A per-file gate on the flagged quadrant keeps each gap closed once paid for, which is the only durable form of coverage progress.