mirror of
https://github.com/greedychipmunk/agent-skills.git
synced 2026-09-14 20:46:42 +08:00
7.4 KiB
7.4 KiB
Code Coverage Analysis Guide
Understanding Code Coverage
Code coverage measures what percentage of your code is executed by your tests. It's an important metric for test quality.
Coverage Types
| Type | Measures | Target |
|---|---|---|
| Line Coverage | Percentage of lines executed | 80%+ |
| Branch Coverage | Percentage of conditional branches executed | 75%+ |
| Function Coverage | Percentage of functions called | 80%+ |
| Statement Coverage | Percentage of statements executed | 80%+ |
Using Istanbul/NYC for Coverage
Installation
npm install --save-dev istanbul nyc
Configuration
In package.json:
{
"scripts": {
"test": "karma start",
"test:coverage": "karma start --coverage"
}
}
In karma.conf.js:
coverageReporter: {
dir: require('path').join(__dirname, 'coverage'),
subdir: '.',
reporters: [
{ type: 'html' },
{ type: 'text-summary' },
{ type: 'lcov' }
],
check: {
global: {
statements: 80,
branches: 75,
functions: 80,
lines: 80
}
}
}
Running Coverage
npm run test:coverage
Interpreting Coverage Reports
HTML Report
The coverage report generates an index.html file:
coverage/
├── index.html (Main report)
├── base/
│ ├── src/
│ │ ├── services/
│ │ │ ├── UserService.js (Coverage details)
│ │ │ └── user.service.html
│ │ └── controllers/
│ │ ├── UserController.js
│ │ └── user.controller.html
Reading Coverage Numbers
Statements : 85.5% ( 320/375 ) ← 320 of 375 statements executed
Branches : 78.2% ( 86/110 ) ← 78% of conditional branches covered
Functions : 82.1% ( 32/39 ) ← 82% of functions called
Lines : 86.3% ( 298/345 ) ← 86% of lines executed
Visual Indicators
// ✓ Line executed (green)
if (user) {
console.log(user.name);
}
// ✗ Line not executed (red)
if (admin) {
deleteAllData(); // This code path not tested
}
// ~ Branch not fully covered (yellow)
if (user && user.active) { // Some branches missing
doSomething();
}
Improving Coverage
Finding Coverage Gaps
- Open
coverage/index.htmlin browser - Look for red (uncovered) lines
- Check yellow (partially covered) branches
- Identify missing test scenarios
Common Coverage Gaps
Error Handling
// BAD: No error handling test
service.getUser = function(id) {
return $http.get('/api/users/' + id);
};
// GOOD: Test error path
it('should handle 404 errors', function() {
$httpBackend.expectGET('/api/users/999').respond(404);
var error;
service.getUser(999).then(null, function(err) {
error = err;
});
$httpBackend.flush();
expect(error).toBeDefined();
});
Conditional Branches
// BAD: Only testing happy path
controller.submit = function() {
if (form.$valid) {
service.save(form.data);
}
};
it('should save when form is valid', function() {
$scope.form = { $valid: true, data: {} };
$scope.submit();
// Only tests valid branch!
});
// GOOD: Test both branches
it('should not save when form is invalid', function() {
$scope.form = { $valid: false };
$scope.submit();
expect(service.save).not.toHaveBeenCalled();
});
Edge Cases
// BAD: Not testing edge cases
function processUsers(users) {
return users.map(function(user) {
return user.name.toUpperCase();
});
}
// GOOD: Test edge cases
it('should handle empty array', function() {
expect(processUsers([])).toEqual([]);
});
it('should handle null users', function() {
expect(function() {
processUsers([null]);
}).toThrow();
});
it('should handle users without names', function() {
expect(function() {
processUsers([{}]);
}).toThrow();
});
Loop Coverage
// BAD: Incomplete loop testing
for (var i = 0; i < items.length; i++) {
if (items[i].active) {
results.push(items[i]);
}
}
// GOOD: Test different loop scenarios
it('should process all items', function() {
var items = [
{ active: true },
{ active: false },
{ active: true }
];
expect(processItems(items).length).toBe(2);
});
Coverage-Driven Testing
Workflow
- Run tests with coverage
- Identify uncovered code
- Write tests for uncovered paths
- Re-run coverage
- Repeat until target reached
Example
// 1. Run coverage
npm run test:coverage
// Coverage: 65%
// 2. Add missing tests for error handling
it('should handle timeouts', function() {
$timeout(function() {
expect(true).toBe(true);
}, 5000);
$timeout.flush();
});
// 3. Re-run coverage
npm run test:coverage
// Coverage: 78%
// 4. Continue improving
Coverage Best Practices
| ✓ Do | ✗ Don't |
|---|---|
| Test error paths | Only test happy paths |
| Test edge cases | Test only main scenarios |
| Test boundary values | Ignore edge cases |
| Test false conditions | Only test true conditions |
| Test async operations | Skip async tests |
| Track coverage trends | Ignore coverage metrics |
Coverage Reporting
Text Summary
TOTAL: 85.5%
PASS: ✓ 150 tests passed
WARNINGS: 5 files below threshold
CI/CD Integration
GitHub Actions
- name: Test Coverage
run: npm run test:coverage
- name: Upload Coverage
uses: codecov/codecov-action@v2
with:
files: ./coverage/lcov.info
Jenkins
stage('Coverage') {
steps {
sh 'npm run test:coverage'
publishHTML([
reportDir: 'coverage',
reportFiles: 'index.html',
reportName: 'Coverage Report'
])
}
}
Managing Coverage Thresholds
Setting Thresholds
// karma.conf.js
coverageReporter: {
check: {
global: {
statements: 80,
branches: 75,
functions: 80,
lines: 80
},
each: {
statements: 70,
branches: 65,
functions: 70,
lines: 70
}
}
}
Excluding Code from Coverage
// Skip coverage for this file
// istanbul ignore file
// Skip single line
/* istanbul ignore next */
if (process.env.NODE_ENV === 'test') { ... }
// Skip next line
/* istanbul ignore next */
console.log('Debug info');
Common Coverage Challenges
Challenge 1: Circular Dependencies
// Mock circular deps in tests
beforeEach(module(function($provide) {
$provide.value('ServiceA', mockServiceA);
$provide.value('ServiceB', mockServiceB);
}));
Challenge 2: Browser APIs
// Mock browser APIs
beforeEach(function() {
spyOn(localStorage, 'getItem').and.returnValue('value');
spyOn(window, 'alert');
});
Challenge 3: Heavy Setup Code
// Extract setup to helper functions
function setupDatabase() {
// Complex setup
}
function setupAuth() {
// Auth setup
}
beforeEach(function() {
setupDatabase();
setupAuth();
});
Coverage Tools Comparison
| Tool | Language | Integration | Report |
|---|---|---|---|
| Istanbul | JavaScript | Karma | HTML, LCOV |
| NYC | JavaScript | CLI | HTML, JSON |
| Coveralls | Multi | CI/CD | Web |
| Codecov | Multi | CI/CD | Web |
References
Last Updated: January 10, 2026