| name | Test Coverage Improvement Expert |
| description | Analyze test coverage and add new test cases to improve coverage without changing implementation |
| category | Quality |
| tags | testing, coverage, quality, test-cases, tdd |
Test Coverage Improvement Expert Skill
When to Use This Skill
This skill automatically activates when:
- User asks about test coverage
- User mentions "coverage", "test coverage", or "add tests"
- Working on improving test quality
- User asks to increase coverage percentage
- Reviewing coverage reports
Coverage Improvement Process
Step 1: Run Coverage Analysis
Detect project type and run appropriate coverage tool:
Foundry/Solidity
forge coverage --report summary
forge coverage --report lcov # For detailed report
Jest (Next.js/React/Node.js)
npm run test:coverage
# or
jest --coverage
Vitest
vitest --coverage
# or
npm run test:coverage
Other
- Detect from
package.jsonscripts - Use project-specific coverage tools
Step 2: Identify Uncovered Code
Analyze coverage report for:
- Functions with low coverage (<80%)
- Uncovered branches
- If statements
- Ternary operators
- Logical operators (&&, ||)
- Error cases not tested
- Error throws/reverts
- Catch blocks
- Validation failures
- Edge cases
- Zero values
- Maximum values
- Empty arrays/strings
- Null/undefined handling
- State transitions
- State machine transitions
- Multi-step processes
Step 3: Prioritize Test Cases
Priority order for new tests:
- Critical paths - Core business logic (target: 100%)
- Security-critical - Auth, permissions, validation
- Complex logic - High cyclomatic complexity
- Error handling - All error conditions
- Edge cases - Boundary conditions
- Utilities - Helper functions
Step 4: Write New Tests
Test Writing Guidelines
Critical Rule: DO NOT Modify Implementation
- ONLY add new test cases
- DO NOT change production code
- DO NOT refactor existing tests
- DO NOT change test behavior
Follow Existing Patterns
Study existing tests and match:
- File organization
- Naming conventions
- Setup/teardown patterns
- Assertion style
Use Descriptive Names
// Good: Describes scenario and expected outcome
it('should return 401 when user is not authenticated', () => {})
it('should throw ValidationError when amount is negative', () => {})
// Bad: Vague or incomplete
it('works', () => {})
it('test error', () => {})
Test Structure
Follow Arrange-Act-Assert pattern:
it('should calculate total with discount', () => {
// Arrange
const cart = createCart([item1, item2]);
const discount = 0.1;
// Act
const total = cart.calculateTotal(discount);
// Assert
expect(total).toBe(expectedTotal);
});
Project-Specific Patterns
Foundry/Solidity
// test/MyContract.t.sol
// Test successful case
function test_Deposit_Success() public {
uint256 amount = 1 ether;
vm.deal(user, amount);
vm.prank(user);
myContract.deposit{value: amount}();
assertEq(myContract.balances(user), amount);
}
// Test revert case
function test_RevertWhen_InsufficientBalance() public {
vm.prank(user);
vm.expectRevert(MyContract.InsufficientBalance.selector);
myContract.withdraw(1 ether);
}
// Test edge case
function test_Deposit_ZeroAmount() public {
vm.prank(user);
vm.expectRevert(MyContract.InvalidAmount.selector);
myContract.deposit{value: 0}();
}
Jest/TypeScript
// __tests__/api/users.test.ts
describe('GET /api/users', () => {
// Success case
it('should return users when authenticated', async () => {
mockAuth.mockResolvedValue({ user: testUser });
const res = await request(app).get('/api/users');
expect(res.status).toBe(200);
expect(res.body.data).toHaveLength(3);
});
// Error case
it('should return 401 when not authenticated', async () => {
mockAuth.mockResolvedValue(null);
const res = await request(app).get('/api/users');
expect(res.status).toBe(401);
});
// Edge case
it('should return empty array when no users exist', async () => {
mockDb.users.findMany.mockResolvedValue([]);
const res = await request(app).get('/api/users');
expect(res.body.data).toEqual([]);
});
});
React Component Tests
// components/__tests__/Button.test.tsx
describe('Button', () => {
it('should render with text', () => {
render(<Button>Click me</Button>);
expect(screen.getByText('Click me')).toBeInTheDocument();
});
it('should call onClick when clicked', () => {
const onClick = jest.fn();
render(<Button onClick={onClick}>Click</Button>);
fireEvent.click(screen.getByText('Click'));
expect(onClick).toHaveBeenCalledTimes(1);
});
it('should be disabled when disabled prop is true', () => {
render(<Button disabled>Click</Button>);
expect(screen.getByRole('button')).toBeDisabled();
});
it('should show loading state', () => {
render(<Button loading>Click</Button>);
expect(screen.getByTestId('loading-spinner')).toBeInTheDocument();
});
});
Coverage Goals
Target coverage by area:
| Area | Target | Priority |
|---|---|---|
| Critical paths | 100% | Highest |
| Business logic | 90%+ | High |
| Utilities | 80%+ | Medium |
| UI components | 70%+ | Lower |
Focus on:
- Security-critical functions
- Complex business logic
- Error handling
- Edge cases
Verification
After adding tests:
Run all tests
# Foundry forge test # Jest/Vitest npm testRe-run coverage
# Foundry forge coverage --report summary # Jest npm run test:coverageVerify improvement
- Coverage increased (target: +5% or more)
- No test failures
- No regressions
Output Format
After adding tests:
## Coverage Improvement Summary
### Before
- Overall: 65%
- src/utils/: 45%
- src/api/: 70%
### After
- Overall: 78% (+13%)
- src/utils/: 85% (+40%)
- src/api/: 82% (+12%)
### Tests Added
1. `test/utils/format.test.ts` - 12 new tests
- Edge cases for date formatting
- Error handling for invalid inputs
2. `test/api/users.test.ts` - 8 new tests
- Unauthorized access tests
- Pagination edge cases
### Files Modified
- `test/utils/format.test.ts` (new)
- `test/api/users.test.ts` (modified)
### Verification
- [x] All tests pass
- [x] Coverage increased by 13%
- [x] No regressions
Integration with CI/CD
name: Improve Coverage
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * 0" # Weekly
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci
- uses: teliha/dev-workflows/.github/actions/improve-coverage@main
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github_token: ${{ secrets.GITHUB_TOKEN }}