# Test Coverage Threshold Not Met

Common Error Patterns

Test coverage failures typically show:

bash
Coverage threshold not met. Lines: 75% (required: 80%)
bash
ERROR: Coverage check failed: Coverage is below minimum threshold
bash
Overall line coverage: 72.5% (threshold: 80%)
ERROR: Quality gate failed
bash
Coverage threshold violation: 50% < 80% minimum

Root Causes and Solutions

1. Insufficient Test Coverage

Not enough tests covering application code.

Solution:

Identify uncovered code:

```bash # Generate coverage report npm test -- --coverage

# View detailed report cat coverage/lcov-report/index.html

# For Jest jest --coverage --coverageDirectory=coverage

# For Python pytest --cov=src --cov-report=html coverage report -m ```

Focus on critical paths:

```bash # Check specific file coverage jest --coverage --collectCoverageFrom='src/utils/**' src/utils/test.ts

# Coverage for specific functions coverage report -m --include=src/main.py ```

Write tests for uncovered areas:

```javascript // Example: Testing uncovered utility function describe('formatDate', () => { it('should format date correctly', () => { expect(formatDate('2024-01-01')).toBe('January 1, 2024'); });

it('should handle invalid input', () => { expect(formatDate(null)).toBe('Invalid date'); }); }); ```

2. Coverage Configuration Incorrect

Coverage threshold configuration is wrong.

Solution:

Configure coverage thresholds:

json
// jest.config.json
{
  "coverageThreshold": {
    "global": {
      "branches": 80,
      "functions": 80,
      "lines": 80,
      "statements": 80
    },
    "./src/utils/": {
      "branches": 100,
      "functions": 100,
      "lines": 100
    }
  }
}

For package.json:

json
{
  "jest": {
    "coverageThreshold": {
      "global": {
        "lines": 80
      }
    }
  }
}

For Istanbul/nyc:

json
// .nycrc
{
  "check-coverage": true,
  "lines": 80,
  "branches": 80,
  "functions": 80,
  "statements": 80
}

For Python pytest-cov:

```toml # pyproject.toml [tool.pytest.ini_options] addopts = "--cov --cov-fail-under=80"

[tool.coverage.run] source = ["src"]

[tool.coverage.report] fail_under = 80 ```

3. Coverage Exclusions Not Applied

Generated or external code counted in coverage.

Solution:

Exclude unnecessary files:

json
// jest.config.json
{
  "collectCoverageFrom": [
    "src/**/*.{js,jsx,ts,tsx}",
    "!src/**/*.d.ts",
    "!src/**/__tests__/**",
    "!src/**/__mocks__/**",
    "!src/**/index.ts",
    "!src/types/**"
  ]
}

For Istanbul/nyc:

json
// .nycrc
{
  "include": ["src/**"],
  "exclude": [
    "src/**/*.d.ts",
    "src/**/__tests__/**",
    "src/types/**"
  ]
}

For Python:

toml
# pyproject.toml
[tool.coverage.omit]
paths = [
    "*/tests/*",
    "*/__init__.py",
    "*/migrations/*"
]

4. Coverage Tool Mismatch

Different coverage tools producing different results.

Solution:

Use consistent coverage tool:

```yaml # GitHub Actions - name: Run tests with coverage run: npm test -- --coverage --coverageReporters=json-summary

  • name: Check coverage threshold
  • run: |
  • COVERAGE=$(cat coverage/coverage-summary.json | jq '.total.lines.pct')
  • if [ "$COVERAGE" -lt 80 ]; then
  • echo "Coverage $COVERAGE% is below threshold 80%"
  • exit 1
  • fi
  • `

For multiple reporters:

json
// jest.config.json
{
  "coverageReporters": ["text", "lcov", "json-summary", "html"]
}

5. CI Configuration Not Running Coverage

CI pipeline skips coverage step.

Solution:

Add coverage step to CI:

```yaml # GitHub Actions - name: Run tests run: npm test

  • name: Generate coverage
  • run: npm test -- --coverage
  • name: Upload coverage
  • uses: codecov/codecov-action@v4
  • with:
  • token: ${{ secrets.CODECOV_TOKEN }}
  • fail_ci_if_error: true
  • `

For GitLab CI:

yaml
test:
  script:
    - npm install
    - npm test -- --coverage
  coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'

For Jenkins:

groovy
stage('Test') {
  steps {
    sh 'npm test -- --coverage'
  }
  post {
    always {
      publishHTML target: [
        allowMissing: false,
        alwaysLinkToLastBuild: true,
        keepAll: true,
        reportDir: 'coverage',
        reportFiles: 'index.html',
        reportName: 'Coverage Report'
      ]
    }
  }
}

6. External Coverage Service Integration

Codecov/Coveralls integration failing.

Solution:

For Codecov:

yaml
# GitHub Actions
- name: Upload to Codecov
  uses: codecov/codecov-action@v4
  with:
    token: ${{ secrets.CODECOV_TOKEN }}
    files: ./coverage/lcov.info
    flags: unittests
    name: codecov-umbrella
    fail_ci_if_error: true
    verbose: true

For Coveralls:

yaml
- name: Coveralls
  uses: coverallsapp/github-action@v2
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}

Configure Codecov yaml:

```yaml # codecov.yml coverage: status: project: default: target: 80% threshold: 5% patch: default: target: 80%

ignore: - "src/types/**" - "**/*.d.ts" - "/__tests__/" ```

7. Coverage History/Delta Issues

Coverage decreased from previous commit.

Solution:

Configure coverage delta rules:

yaml
# codecov.yml
coverage:
  status:
    project:
      default:
        target: auto  # Compare against previous commit
        threshold: 5%  # Allow 5% decrease

Track coverage history:

```yaml # GitHub Actions - store coverage artifacts - name: Upload coverage artifact uses: actions/upload-artifact@v4 with: name: coverage-report path: coverage/

  • name: Download previous coverage
  • uses: actions/download-artifact@v4
  • with:
  • name: coverage-report
  • path: previous-coverage/
  • `

8. Flaky Tests Affecting Coverage

Tests pass/fail inconsistently, affecting coverage.

Solution:

Detect flaky tests:

```bash # Run tests multiple times npm test -- --coverage --runInBand --detectOpenHandles

# Jest detect flaky tests jest --coverage --forceExit --detectOpenHandles ```

Exclude flaky tests:

json
// jest.config.json
{
  "testPathIgnorePatterns": [
    "/node_modules/",
    "<rootDir>/src/flaky/"
  ]
}

Coverage Tools Configuration

Jest Coverage

json
{
  "jest": {
    "collectCoverage": true,
    "coverageDirectory": "coverage",
    "coverageReporters": ["text", "lcov", "json"],
    "coverageThreshold": {
      "global": {
        "branches": 80,
        "functions": 80,
        "lines": 80,
        "statements": -10  # Allow 10 uncovered lines
      }
    },
    "collectCoverageFrom": [
      "src/**/*.{js,ts}",
      "!src/**/*.d.ts"
    ]
  }
}

Istanbul/nyc Coverage

json
{
  "nyc": {
    "check-coverage": true,
    "lines": 80,
    "statements": 80,
    "functions": 80,
    "branches": 80,
    "reporter": ["lcov", "text", "html"],
    "exclude": ["test/**", "coverage/**"]
  }
}

pytest-cov Coverage

```toml [tool.pytest.ini_options] addopts = [ "--cov=src", "--cov-report=term-missing", "--cov-report=html", "--cov-fail-under=80" ]

[tool.coverage.run] branch = true source = ["src"] omit = ["tests/*", "*/__init__.py"]

[tool.coverage.report] show_missing = true fail_under = 80 ```

JaCoCo Coverage (Java)

xml
<plugin>
  <groupId>org.jacoco</groupId>
  <artifactId>jacoco-maven-plugin</artifactId>
  <version>0.8.11</version>
  <executions>
    <execution>
      <goals>
        <goal>prepare-agent</goal>
      </goals>
    </execution>
    <execution>
      <id>check</id>
      <goals>
        <goal>check</goal>
      </goals>
      <configuration>
        <rules>
          <rule>
            <element>BUNDLE</element>
            <limits>
              <limit>
                <counter>LINE</counter>
                <value>COVEREDRATIO</value>
                <minimum>0.80</minimum>
              </limit>
            </limits>
          </rule>
        </rules>
      </configuration>
    </execution>
  </executions>
</plugin>

Debugging Commands

```bash # Jest verbose coverage jest --coverage --verbose --debug

# Show uncovered lines jest --coverage --coverageReporters=text

# Coverage for specific file jest --coverage --collectCoverageFrom='src/file.ts' src/file.test.ts

# Istanbul detailed report nyc report --reporter=text

# Python coverage details coverage report -m --sort=cover coverage html open htmlcov/index.html

# Maven coverage report mvn jacoco:report ```

Quick Reference

Coverage TypeTargetConfig
Lines80%lines: 80
Branches70-80%branches: 80
Functions80%functions: 80
Statements80%statements: 80

Prevention Tips

  1. 1.Set realistic coverage thresholds
  2. 2.Exclude generated/config files from coverage
  3. 3.Use coverage reporters for detailed reports
  4. 4.Track coverage history with services like Codecov
  5. 5.Set up coverage badges for visibility
  6. 6.Add coverage checks to PR requirements
  • [GitHub Actions Workflow Failed](#)
  • [Jenkins Build Failed](#)
  • [NPM Install Failed in CI](#)