# Test Coverage Threshold Not Met
Common Error Patterns
Test coverage failures typically show:
Coverage threshold not met. Lines: 75% (required: 80%)ERROR: Coverage check failed: Coverage is below minimum thresholdOverall line coverage: 72.5% (threshold: 80%)
ERROR: Quality gate failedCoverage threshold violation: 50% < 80% minimumRoot 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:
// jest.config.json
{
"coverageThreshold": {
"global": {
"branches": 80,
"functions": 80,
"lines": 80,
"statements": 80
},
"./src/utils/": {
"branches": 100,
"functions": 100,
"lines": 100
}
}
}For package.json:
{
"jest": {
"coverageThreshold": {
"global": {
"lines": 80
}
}
}
}For Istanbul/nyc:
// .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:
// jest.config.json
{
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
"!src/**/*.d.ts",
"!src/**/__tests__/**",
"!src/**/__mocks__/**",
"!src/**/index.ts",
"!src/types/**"
]
}For Istanbul/nyc:
// .nycrc
{
"include": ["src/**"],
"exclude": [
"src/**/*.d.ts",
"src/**/__tests__/**",
"src/types/**"
]
}For Python:
# 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:
// 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:
test:
script:
- npm install
- npm test -- --coverage
coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'For Jenkins:
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:
# 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: trueFor Coveralls:
- 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:
# codecov.yml
coverage:
status:
project:
default:
target: auto # Compare against previous commit
threshold: 5% # Allow 5% decreaseTrack 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:
// jest.config.json
{
"testPathIgnorePatterns": [
"/node_modules/",
"<rootDir>/src/flaky/"
]
}Coverage Tools Configuration
Jest Coverage
{
"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
{
"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)
<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 Type | Target | Config |
|---|---|---|
| Lines | 80% | lines: 80 |
| Branches | 70-80% | branches: 80 |
| Functions | 80% | functions: 80 |
| Statements | 80% | statements: 80 |
Prevention Tips
- 1.Set realistic coverage thresholds
- 2.Exclude generated/config files from coverage
- 3.Use coverage reporters for detailed reports
- 4.Track coverage history with services like Codecov
- 5.Set up coverage badges for visibility
- 6.Add coverage checks to PR requirements
Related Articles
- [GitHub Actions Workflow Failed](#)
- [Jenkins Build Failed](#)
- [NPM Install Failed in CI](#)