Test Coverage and Metrics
Test coverage measures how much code is tested. This article covers coverage metrics and best practices.
Introduction
Test coverage provides:
- Code quality metrics
- Testing completeness
- Risk identification
- Quality gates
- Improvement tracking
Understanding coverage helps you:
- Measure test completeness
- Identify untested code
- Set quality targets
- Improve code quality
- Track progress
Coverage Types
Line Coverage
// โ
Good: Line coverage
function calculateTotal(items) {
let total = 0; // Line 1
for (const item of items) { // Line 2
total += item.price; // Line 3
}
return total; // Line 4
}
// Test covers all lines
test('calculates total', () => {
expect(calculateTotal([{ price: 10 }, { price: 20 }])).toBe(30);
});
Branch Coverage
// โ
Good: Branch coverage
function getDiscount(amount) {
if (amount > 100) { // Branch 1
return 0.1;
} else if (amount > 50) { // Branch 2
return 0.05;
} else { // Branch 3
return 0;
}
}
// Test all branches
test('returns 10% discount for amount > 100', () => {
expect(getDiscount(150)).toBe(0.1);
});
test('returns 5% discount for amount > 50', () => {
expect(getDiscount(75)).toBe(0.05);
});
test('returns no discount for amount <= 50', () => {
expect(getDiscount(30)).toBe(0);
});
Function Coverage
// โ
Good: Function coverage
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
function multiply(a, b) {
return a * b;
}
// Test all functions
test('add function', () => {
expect(add(2, 3)).toBe(5);
});
test('subtract function', () => {
expect(subtract(5, 3)).toBe(2);
});
test('multiply function', () => {
expect(multiply(2, 3)).toBe(6);
});
Coverage Configuration
Jest Coverage
// โ
Good: Jest coverage config
// jest.config.js
module.exports = {
collectCoverageFrom: [
'src/**/*.js',
'!src/index.js',
'!src/**/*.test.js',
'!src/**/__mocks__/**'
],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80
},
'./src/utils/': {
branches: 90,
functions: 90,
lines: 90,
statements: 90
}
},
coverageReporters: ['text', 'lcov', 'html']
};
// Run coverage
npm test -- --coverage
Coverage Reports
# โ
Good: Generate coverage report
npm test -- --coverage
# โ
Good: View HTML report
open coverage/lcov-report/index.html
# โ
Good: Generate JSON report
npm test -- --coverage --coverageReporters=json
# โ
Good: Upload to Codecov
npm install --save-dev codecov
codecov
Coverage Metrics
Measuring Coverage
// โ
Good: Track coverage metrics
const coverageMetrics = {
lines: 85,
branches: 80,
functions: 90,
statements: 85
};
// โ
Good: Set targets
const targets = {
lines: 80,
branches: 75,
functions: 80,
statements: 80
};
// โ
Good: Check if targets met
function checkCoverage(metrics, targets) {
for (const [key, value] of Object.entries(targets)) {
if (metrics[key] < value) {
console.error(`${key} coverage ${metrics[key]}% below target ${value}%`);
return false;
}
}
return true;
}
Best Practices
-
Set realistic targets:
// โ Good: Realistic targets coverageThreshold: { global: { lines: 80, branches: 75, functions: 80 } } // โ Bad: Unrealistic targets coverageThreshold: { global: { lines: 100, branches: 100, functions: 100 } } -
Focus on critical code:
// โ Good: Higher coverage for critical code './src/utils/': { lines: 95, branches: 90 }, './src/components/': { lines: 80, branches: 75 } // โ Bad: Same coverage for all code -
Exclude generated code:
// โ Good: Exclude generated code collectCoverageFrom: [ 'src/**/*.js', '!src/**/*.generated.js', '!src/**/__mocks__/**' ] // โ Bad: Include everything collectCoverageFrom: ['src/**/*.js']
Summary
Test coverage is important. Key takeaways:
- Measure coverage types
- Set realistic targets
- Focus on critical code
- Exclude generated code
- Track metrics
- Improve incrementally
- Use coverage reports
- Maintain quality gates
Related Resources
Next Steps
- Learn about CI/CD
- Explore Test Automation
- Study Performance Testing
- Practice coverage measurement
- Improve code quality
Comments