Skip to main content

Code Coverage Best Practices

Code Coverage Best Practices treat coverage as a way to find untested code, not a quality target to game. Emphasizing diff coverage and strong assertions keeps the metric honest and useful as code and migrations evolve.

Best Practice: Code Coverage Best Practices

Code coverage measures which lines, branches, or paths your tests execute. Used well, it highlights code that no test touches at all. Used poorly, it becomes a vanity metric that teams game with assertion-free tests. Google's guidance frames coverage as a tool to find untested code, not as a quality guarantee or a hard target. High coverage with weak assertions proves little, while moderate coverage with strong, behavior-focused assertions can be far more valuable. The most actionable form is diff (patch) coverage, which asks whether new and changed code is tested rather than chasing a global percentage.

Step-by-Step Implementation Guidance

  1. Enable coverage collection in your test runner and report line and branch coverage.
  2. Treat coverage as a discovery tool: review uncovered, high-risk code paths.
  3. Enforce diff coverage on pull requests so new code arrives tested.
  4. Avoid rigid global targets that incentivize meaningless tests.
  5. Pair coverage with assertion quality checks such as mutation testing on critical modules.
  6. Exclude generated code and trivial accessors to keep numbers meaningful.
  7. Publish trends to spot erosion early without punishing healthy refactors.

Common Mistakes Teams Make When Ignoring This Practice

  • Setting a single high global target and writing assertion-free tests to hit it.
  • Confusing coverage with correctness or test quality.
  • Ignoring branch coverage and missing untested conditional paths.
  • Counting generated or boilerplate code in the metric.
  • Blocking refactors because a percentage dipped slightly.

Tools and Techniques That Support This Practice

  • Coverage engines: JaCoCo, Coverage.py, Istanbul/nyc, Go cover.
  • Diff/patch coverage gates: Codecov, Coveralls, SonarQube.
  • Branch and condition coverage reporting.
  • Mutation testing to validate assertion strength.
  • CI integration to surface coverage on every pull request.

How This Practice Applies to Different Migration Types

  • Cloud Migration: Use coverage to confirm portable logic is tested before relocating it.
  • Database Migration: Check that data-access and mapping code paths are exercised on the new engine.
  • SaaS Migration: Ensure adapter and integration code for the new provider is covered.
  • Codebase Migration: Raise coverage of legacy code to form a safety net before refactoring.

Checklist

  • Coverage collection reports both line and branch metrics.
  • Coverage is used to find untested code, not as a sole target.
  • Diff coverage is enforced on pull requests.
  • Assertion quality is validated, not just execution.
  • Generated and trivial code is excluded.
  • Coverage trends are tracked over time.
  • Refactoring is not blocked by minor percentage changes.