Skip to content

Jest Coverage Thresholds

Coverage thresholds let you fail a build automatically if coverage drops below an agreed-upon minimum. This lesson covers Jest's coverageThreshold configuration option and how to apply it globally or per file group.

Setting a Global Coverage Threshold

coverageThreshold in jest.config.js defines minimum percentages for statements, branches, functions, and lines. If the actual coverage falls below any configured minimum after a test run, Jest exits with a non-zero code, failing the build in CI.

This turns coverage from a passive report into an enforced quality gate, preventing coverage from silently eroding over time as new, untested code gets added.

// jest.config.js
module.exports = {
  collectCoverage: true,
  coverageThreshold: {
    global: {
      statements: 80,
      branches: 70,
      functions: 80,
      lines: 80,
    },
  },
};

If any of the four metrics falls below its threshold, jest --coverage exits with a failing status code.

Per-File or Per-Glob Thresholds

module.exports = {
  coverageThreshold: {
    global: { statements: 75 },
    './src/payments/**/*.js': {
      statements: 95,
      branches: 90,
    },
  },
};
  • A glob pattern key applies a stricter (or looser) threshold to matching files specifically.
  • This is useful for enforcing higher standards on business-critical code (like payments) than the rest of the codebase.
  • Thresholds can be negative numbers, meaning "allow up to N uncovered items" instead of a percentage.
  • Files matched by a specific glob are excluded from the global threshold calculation.

Coverage Thresholds Cheat Sheet

How to configure and interpret coverageThreshold.

Setting Meaning
global: { statements: 80 } Whole-project minimum: 80% statements covered
'./src/x/**': { branches: 90 } Stricter threshold for a specific folder
Positive number (e.g. 80) Minimum percentage required
Negative number (e.g. -5) Maximum number of uncovered items allowed
Build fails if unmet Non-zero exit code from jest --coverage

Ratcheting Coverage Up Gradually

For a legacy codebase with low existing coverage, setting an ambitious threshold immediately will just fail every build. Instead, set the threshold at (or slightly above) the current coverage level, then raise it gradually over time as tests are added, preventing regressions without demanding an unrealistic rewrite.

  • Measure current coverage as a starting baseline.
  • Set the threshold at or just above that baseline.
  • Raise the threshold incrementally as coverage improves over subsequent releases.

Enforcing Thresholds in CI Pipelines

Because jest --coverage already exits with a failing status code when a threshold isn't met, no extra CI-specific tooling is required — a standard npm test (or jest --coverage --ci) step in your pipeline will fail the build automatically.

// package.json
{
  "scripts": {
    "test:ci": "jest --coverage --ci"
  }
}

Common Mistakes

  • Setting an unrealistically high threshold on a legacy codebase, immediately breaking every build.
  • Forgetting per-glob thresholds override (not add to) the global threshold for matching files.
  • Not distinguishing between a percentage threshold and a negative "allowed uncovered count" threshold.
  • Enforcing thresholds locally but forgetting to add the check to the actual CI pipeline.

Key Takeaways

  • coverageThreshold fails the test run if coverage drops below configured minimums.
  • Per-glob thresholds let you enforce stricter standards for critical code paths.
  • Start thresholds near your current baseline and raise them gradually over time.
  • No extra tooling is needed to enforce this in CI — Jest's own exit code handles it.

Pro Tip

Set a stricter coverageThreshold for your most business-critical folder (payments, auth, billing) than for the rest of the codebase — it focuses your team's testing effort where mistakes are most costly.