Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Analyze test coverage gaps and generate tests to improve coverage. Use when improving test coverage, finding untested code, or writing missing tests.
.claude/skills/onewave-ai-test-coverage-improver/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | -9% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 21% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 4% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 42% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 61% | 0% |
When improving test coverage:
bash# Jest npx jest --coverage # Vitest npx vitest --coverage # NYC (Istanbul) for any test runner npx nyc npm test # View HTML report open coverage/lcov-report/index.html
| Type | Minimum | Good | Excellent | |------|---------|------|-----------| | Lines | 70% | 80% | 90%+ | | Branches | 60% | 75% | 85%+ | | Functions | 70% | 80% | 90%+ | | Statements | 70% | 80% | 90%+ |
typescriptimport { describe, it, expect, vi, beforeEach } from 'vitest'; import { calculateTotal, formatCurrency } from './utils'; describe('calculateTotal', () => { it('should sum all item prices', () => { const items = [ { price: 10, quantity: 2 }, { price: 5, quantity: 1 }, ]; expect(calculateTotal(items)).toBe(25); }); it('should return 0 for empty array', () => { expect(calculateTotal([])).toBe(0); }); it('should handle decimal prices', () => { const items = [{ price: 10.99, quantity: 1 }]; expect(calculateTotal(items)).toBeCloseTo(10.99); }); });
typescriptdescribe('fetchUser', () => { it('should return user data', async () => { const user = await fetchUser(1); expect(user).toEqual({ id: 1, name: expect.any(String), email: expect.stringContaining('@'), }); }); it('should throw for non-existent user', async () => { await expect(fetchUser(999)).rejects.toThrow('User not found'); }); });
typescriptimport { vi } from 'vitest'; import { sendEmail } from './email'; import { createUser } from './user'; vi.mock('./email', () => ({ sendEmail: vi.fn().mockResolvedValue({ success: true }), })); describe('createUser', () => { beforeEach(() => { vi.clearAllMocks(); }); it('should send welcome email after creating user', async () => { await createUser({ name: 'John', email: 'john@test.com' }); expect(sendEmail).toHaveBeenCalledWith({ to: 'john@test.com', template: 'welcome', }); }); });
tsximport { render, screen, fireEvent } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { Button } from './Button'; describe('Button', () => { it('should render children', () => { render(<Button>Click me</Button>); expect(screen.getByText('Click me')).toBeInTheDocument(); }); it('should call onClick when clicked', async () => { const handleClick = vi.fn(); render(<Button onClick={handleClick}>Click</Button>); await userEvent.click(screen.getByRole('button')); expect(handleClick).toHaveBeenCalledTimes(1); }); it('should be disabled when loading', () => { render(<Button isLoading>Submit</Button>); expect(screen.getByRole('button')).toBeDisabled(); }); });
typescriptimport { createMocks } from 'node-mocks-http'; import handler from './api/users'; describe('GET /api/users', () => { it('should return users list', async () => { const { req, res } = createMocks({ method: 'GET' }); await handler(req, res); expect(res._getStatusCode()).toBe(200); expect(JSON.parse(res._getData())).toHaveProperty('users'); }); });
Ensure tests cover:
??)?.)javascript// vitest.config.ts export default { test: { coverage: { provider: 'v8', reporter: ['text', 'html', 'lcov'], exclude: [ 'node_modules/', '**/*.d.ts', '**/*.test.ts', '**/types/', ], thresholds: { lines: 80, branches: 75, functions: 80, statements: 80, }, }, }, };
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 24,554 | 20,940 | -15% | 1 | 1 | 0% | 4,306 | 5,608 | +30% | 0 | 0 | — |
case-02 | fail→fail | 14,123 | 12,212 | -14% | 1 | 1 | 0% | 2,562 | 3,564 | +39% | 0 | 0 | — |
case-03 | fail→fail | 20,927 | 27,269 | +30% | 1 | 1 | 0% | 4,009 | 5,848 | +46% | 0 | 0 | — |
case-04 | pass→pass | 11,448 | 12,446 | +9% | 1 | 1 | 0% | 1,949 | 3,138 | +61% | 0 | 0 | — |
case-05 | fail→fail | 15,388 | 16,238 | +6% | 1 | 1 | 0% | 2,408 | 3,705 | +54% | 0 | 0 | — |
case-06 | fail→fail | 15,376 | 13,084 | -15% | 1 | 1 | 0% | 2,034 | 3,630 | +78% | 0 | 0 | — |
case-07 | fail→pass | 11,776 | 2,498 | -79% | 1 | 1 | 0% | 1,932 | 1,756 | -9% | 0 | 0 | — |
case-08 | pass→pass | 18,000 | 17,964 | -0% | 1 | 1 | 0% | 2,948 | 4,608 | +56% | 0 | 0 | — |
case-09 | pass→pass | 15,739 | 14,637 | -7% | 1 | 1 | 0% | 2,675 | 3,881 | +45% | 0 | 0 | — |
case-10 | pass→pass | 11,253 | 9,741 | -13% | 1 | 1 | 0% | 2,014 | 3,179 | +58% | 0 | 0 | — |
case-11 | pass→pass | 10,920 | 11,787 | +8% | 1 | 1 | 0% | 1,974 | 3,068 | +55% | 0 | 0 | — |
case-12 | fail→pass | 12,968 | 6,936 | -47% | 1 | 1 | 0% | 2,232 | 2,697 | +21% | 0 | 0 | — |
case-13 | fail→pass | 11,779 | 3,365 | -71% | 1 | 1 | 0% | 1,879 | 1,959 | +4% | 0 | 0 | — |
case-14 | fail→pass | 16,653 | 14,575 | -12% | 1 | 1 | 0% | 3,126 | 4,436 | +42% | 0 | 0 | — |
case-15 | pass→pass | 13,943 | 16,640 | +19% | 1 | 1 | 0% | 2,762 | 4,012 | +45% | 0 | 0 | — |
case-16 | pass→pass | 6,727 | 1,528 | -77% | 1 | 1 | 0% | 1,082 | 1,609 | +49% | 0 | 0 | — |
case-17 | pass→pass | 6,935 | 3,049 | -56% | 1 | 1 | 0% | 1,326 | 1,899 | +43% | 0 | 0 | — |
case-18 | pass→pass | 6,533 | 6,549 | +0% | 1 | 1 | 0% | 1,177 | 2,684 | +128% | 0 | 0 | — |
case-19 | pass→pass | 7,753 | 6,365 | -18% | 1 | 1 | 0% | 1,470 | 2,317 | +58% | 0 | 0 | — |
case-20 | pass→pass | 15,637 | 14,312 | -8% | 1 | 1 | 0% | 3,126 | 4,347 | +39% | 0 | 0 | — |
case-21 | pass→pass | 14,180 | 15,879 | +12% | 1 | 1 | 0% | 2,628 | 4,452 | +69% | 0 | 0 | — |
case-22 | pass→pass | 15,027 | 12,362 | -18% | 1 | 1 | 0% | 2,445 | 3,934 | +61% | 0 | 0 | — |
case-23 | pass→pass | 18,332 | 19,771 | +8% | 1 | 1 | 0% | 3,242 | 4,468 | +38% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +17 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.