Test Coverage Analysis Skill
When analyzing test coverage, follow this structured process. The goal is not 100% coverage — it's ensuring the riskiest code is tested well.
1. Discover the Testing Setup
Before analyzing, understand the project's testing landscape:
# Detect testing framework
# Node.js
cat package.json | grep -E "jest|vitest|mocha|ava|tap|playwright|cypress|testing-library"
# Python
cat requirements.txt pyproject.toml setup.cfg 2>/dev/null | grep -E "pytest|unittest|nose|coverage|tox"
# Ruby
cat Gemfile 2>/dev/null | grep -E "rspec|minitest|capybara|factory_bot"
# Go
grep -r "_test.go" --include="*.go" -l .
# Java
cat pom.xml build.gradle 2>/dev/null | grep -E "junit|mockito|testng|jacoco"
# PHP
cat composer.json 2>/dev/null | grep -E "phpunit|pest|mockery"
Identify:
- Testing framework in use (Jest, Vitest, Pytest, RSpec, JUnit, etc.)
- Coverage tool configured (Istanbul/nyc, coverage.py, SimpleCov, JaCoCo, etc.)
- Test directory structure (co-located vs separate test folder)
- Naming conventions (*.test.ts, .spec.ts, test_.py, *_test.go)
- Test types present (unit, integration, e2e, snapshot)
- CI integration (are tests running in CI? is coverage enforced?)
2. Run Existing Coverage
# Node.js (Jest)
npx jest --coverage --coverageReporters=text
# Node.js (Vitest)
npx vitest run --coverage
# Python (Pytest)
python -m pytest --cov=. --cov-report=term-missing
# Go
go test -coverprofile=coverage.out ./...
go tool cover -func=coverage.out
# Ruby (RSpec)
COVERAGE=true bundle exec rspec
# Java (Maven + JaCoCo)
mvn test jacoco:report
# PHP (PHPUnit)
php artisan test --coverage
Record:
- Overall line coverage percentage
- Overall branch coverage percentage
- Files with 0% coverage (completely untested)
- Files with < 50% coverage (poorly tested)
- Uncovered lines (specific line numbers)
3. Identify What's NOT Tested
3a. Find Files Without Tests
# Node.js — find source files without matching test files
find src -name "*.ts" -o -name "*.js" | while read f; do
base=$(basename "$f" | sed 's/\.\(ts\|js\)$//')
if ! find . -name "${base}.test.*" -o -name "${base}.spec.*" | grep -q .; then
echo "NO TEST: $f"
fi
done
# Python — find modules without test files
find src -name "*.py" ! -name "__init__.py" | while read f; do
base=$(basename "$f" .py)
if ! find . -name "test_${base}.py" -o -name "${base}_test.py" | grep -q .; then
echo "NO TEST: $f"
fi
done
# Go — find packages without test files
find . -name "*.go" ! -name "*_test.go" -exec dirname {} \; | sort -u | while read d; do
if ! ls "$d"/*_test.go 2>/dev/null | grep -q .; then
echo "NO TEST: $d"
fi
done
3b. Find Untested Code Paths
Look for these commonly missed patterns:
- Error handlers and catch blocks — the most commonly untested code
- Edge cases — null, undefined, empty arrays, zero, negative numbers, boundary values
- Else branches — the unhappy path in if/else
- Switch default cases — fallback handling
- Early returns and guard clauses — validation at the top of functions
- Timeout and retry logic — what happens when things fail
- Race conditions — concurrent operations
- Cleanup code — finally blocks, destructors, shutdown handlers
- Configuration branches — code that runs differently per environment
- Deprecated or feature-flagged code — code behind flags that's still reachable
3c. Find Dead or Unreachable Code
# Node.js — find unused exports
npx ts-prune
# Python — find unused code
pip install vulture && vulture src/
# General — find functions not referenced anywhere
grep -rn "function\|def\|func " src/ | while read line; do
fname=$(echo "$line" | grep -oP '(?:function|def|func)\s+\K\w+')
count=$(grep -rn "$fname" src/ | wc -l)
if [ "$count" -le 1 ]; then
echo "POSSIBLY UNUSED: $line"
fi
done
4. Risk-Based Prioritization
Not all untested code is equally important. Prioritize by risk:
🔴 Critical — Test These First
- Authentication and authorization — login, signup, password reset, permission checks
- Payment and billing — charge, refund, subscription logic
- Data mutation — create, update, delete operations
- API endpoints — especially public-facing ones
- Input validation — sanitization and parsing of user input
- Security-sensitive code — encryption, token generation, access control
- Core business logic — the main value of your application
🟠 High — Test These Next
- Error handling — catch blocks, error boundaries, fallback behavior
- Database queries — complex queries, transactions, migrations
- Third-party integrations — API calls, webhooks, callbacks
- State management — reducers, stores, state transitions
- File operations — uploads, downloads, processing
- Background jobs — queues, cron jobs, workers
🟡 Medium — Test When Possible
- UI components — interactive components, forms, modals
- Utility functions — helpers, formatters, transformers
- Configuration — environment-specific logic
- Middleware — request/response processing pipeline
- Caching logic — cache invalidation, TTL, fallbacks
🟢 Low — Test If Time Permits
- Static components — presentational components with no logic
- Type definitions — interfaces, types, enums
- Constants and config objects — static values
- Logging — log formatting and output
- Dev-only code — seeders, fixtures, debug utilities
5. Test Quality Analysis
Coverage percentage alone doesn't mean tests are good. Analyze quality:
Assertion Quality
// 🔴 BAD — test runs but asserts nothing meaningful
test('creates user', async () => {
const result = await createUser({ name: 'Alice' });
expect(result).toBeTruthy(); // too vague
});
// ✅ GOOD — specific, meaningful assertions
test('creates user with correct fields', async () => {
const result = await createUser({ name: 'Alice' });
expect(result.id).toBeDefined();
expect(result.name).toBe('Alice');
expect(result.createdAt).toBeInstanceOf(Date);
});
Test Independence
// 🔴 BAD — tests depend on each other's state
let userId;
test('creates user', async () => {
const user = await createUser({ name: 'Alice' });
userId = user.id;
});
test('fetches user', async () => {
const user = await getUser(userId); // depends on previous test
});
// ✅ GOOD — each test sets up its own state
test('fetches user', async () => {
const created = await createUser({ name: 'Alice' });
const fetched = await getUser(created.id);
expect(fetched.name).toBe('Alice');
});
Common Test Smells
- No assertions — test runs code but checks nothing
- Testing implementation, not behavior — brittle tests that break on refactors
- Over-mocking — mocking so much that the test proves nothing
- Flaky tests — tests that pass/fail randomly (timing, order-dependent, network)
- Duplicate tests — same scenario tested multiple times in different places
- Giant test files — 1000+ line test files that are hard to maintain
- Missing cleanup — tests that leave behind state (DB records, files, env vars)
- Snapshot overuse — snapshots accepted without review, hiding regressions
- Copy-paste tests — duplicated setup that should be extracted into helpers
- Happy path only — only testing success, never failure
6. Stack-Specific Checks
Node.js / Jest / Vitest
- Check for missing
afterEach cleanup (open handles, DB connections)
- Verify async tests use
await or return promises (silent failures otherwise)
- Check for missing
jest.mock() cleanup between tests
- Look for
setTimeout in tests without jest.useFakeTimers()
- Verify snapshot tests are intentional and reviewed
- Check for missing error boundary tests in React components
- Verify
act() wrapping on React state updates in tests
- Look for missing
waitFor / findBy on async UI updates
Python / Pytest
- Check for missing
conftest.py fixtures for common setup
- Verify database tests use transactions and rollback (
@pytest.mark.django_db)
- Look for missing
parametrize on tests that should cover multiple inputs
- Check for missing
mock.patch cleanup (use context managers or decorators)
- Verify async tests use
@pytest.mark.asyncio
- Check for missing exception tests (
with pytest.raises(...))
- Look for hardcoded file paths in tests (use
tmp_path fixture)
- Verify test isolation — no tests reading/writing shared state
React / Next.js
- Check for missing
render tests on all user-facing components
- Verify form components test validation, submission, and error states
- Look for missing accessibility tests (
@testing-library/jest-dom matchers)
- Check for untested loading and error states
- Verify hooks are tested with
renderHook from testing-library
- Check for missing tests on context providers and consumers
- Look for untested route guards and redirects
- Verify Server Components have integration tests
- Check for missing tests on API routes / Server Actions
Vue / Nuxt
- Check for missing
mount / shallowMount tests on components
- Verify Pinia stores are tested with
createTestingPinia
- Look for missing
emitted() checks on event emissions
- Check for untested computed properties and watchers
- Verify composables are tested independently
- Check for missing tests on Nuxt middleware and plugins
Go
- Check for missing table-driven tests on functions with multiple inputs
- Verify error return values are tested (not just happy path)
- Look for missing
t.Parallel() on independent tests
- Check for missing
t.Helper() on test utility functions
- Verify interfaces are tested with mock implementations
- Check for missing benchmark tests on performance-critical code (
func BenchmarkX)
- Look for missing
t.Cleanup() for resource teardown
- Verify HTTP handlers are tested with
httptest.NewServer
Java / Spring Boot
- Check for missing
@SpringBootTest integration tests
- Verify
@MockBean is used appropriately (not over-mocked)
- Look for missing
@Transactional on database tests (auto rollback)
- Check for missing controller tests with
MockMvc
- Verify exception handlers are tested
- Check for missing
@ParameterizedTest on multi-input tests
- Look for untested
@Scheduled tasks and async methods
- Verify repository custom queries have integration tests
Ruby / RSpec
- Check for missing
describe blocks for each public method
- Verify
let and before blocks handle proper setup/teardown
- Look for missing
context blocks for different scenarios
- Check for missing
shared_examples for common behavior
- Verify factory definitions cover all required fields (
FactoryBot)
- Check for missing request specs on API endpoints
- Look for untested ActiveRecord callbacks and validations
- Verify background jobs (Sidekiq/Resque) have specs
PHP / Laravel
- Check for missing Feature tests on routes and controllers
- Verify database tests use
RefreshDatabase or DatabaseTransactions
- Look for missing tests on form requests (validation rules)
- Check for missing
assertDatabaseHas / assertDatabaseMissing assertions
- Verify mail, notification, and event fakes are used
- Check for missing tests on Eloquent scopes and accessors
- Look for untested middleware
- Verify queue jobs and listeners have tests
Mobile (React Native / Flutter)
- Check for missing widget/component tests
- Verify navigation flows are tested
- Look for missing tests on platform-specific code (iOS vs Android)
- Check for untested offline/error states
- Verify async storage operations are tested
- Check for missing tests on deep link handling
- Look for untested permission request flows
- Verify API response parsing is tested with realistic mock data
API / Integration Tests
- Check for missing tests on all HTTP methods (GET, POST, PUT, DELETE, PATCH)
- Verify authentication is tested (valid token, expired token, no token, wrong role)
- Look for missing tests on pagination, filtering, and sorting
- Check for missing tests on rate limiting behavior
- Verify webhook handlers are tested with realistic payloads
- Check for missing tests on file upload/download endpoints
- Look for untested CORS behavior
- Verify error responses match API documentation/contract
Database
- Check for missing migration tests (up and rollback)
- Verify complex queries are tested with realistic data volumes
- Look for missing tests on database constraints (unique, foreign key, check)
- Check for untested transaction behavior (commit, rollback, deadlock)
- Verify connection pooling and timeout handling is tested
- Check for missing seed data validation tests
7. Coverage Improvement Plan
After analysis, provide a prioritized plan:
Immediate (This Sprint)
- List specific files and functions to test first based on risk
- Provide test scaffolding for the highest-priority untested code
- Suggest specific test cases with descriptions
Short-Term (Next 2 Sprints)
- Increase coverage on medium-risk areas
- Add integration tests for critical user flows
- Fix test quality issues (weak assertions, flaky tests)
Long-Term (This Quarter)
- Set up coverage thresholds in CI (fail build if coverage drops)
- Add e2e tests for critical user journeys
- Implement mutation testing to verify test effectiveness
- Set up coverage trend tracking
Output Format
Coverage Report
Overall Coverage:
| Metric |
Current |
Target |
Gap |
| Line Coverage |
X% |
80% |
X% |
| Branch Coverage |
X% |
70% |
X% |
| Function Coverage |
X% |
85% |
X% |
Untested Files (by risk):
🔴 Critical — No Tests:
src/auth/login.ts — handles user authentication
src/payments/charge.ts — processes payments
🟠 High — Partial Coverage:
src/api/users.ts — 40% covered, missing error paths
src/db/queries.ts — 55% covered, missing edge cases
Test Quality Issues:
tests/user.test.ts:45 — assertion too vague (toBeTruthy)
tests/order.test.ts — tests are order-dependent
tests/api.test.ts:120 — over-mocked, not testing real behavior
For Each Untested Area
File: src/auth/login.ts
- Risk: 🔴 Critical
- Why it matters: Handles user authentication — bugs here = security breach
- Missing tests:
- Valid login with correct credentials
- Login with wrong password (should return 401)
- Login with non-existent email (should return 401, same message as wrong password)
- Login with expired account
- Rate limiting after 5 failed attempts
- SQL injection attempt in email field
- Session creation and token generation
- Test scaffold:
describe('login', () => {
it('returns a token for valid credentials', async () => { ... });
it('returns 401 for incorrect password', async () => { ... });
it('returns 401 for non-existent email', async () => { ... });
it('locks account after 5 failed attempts', async () => { ... });
it('rejects SQL injection in email', async () => { ... });
});
Summary
End every analysis with:
- Current state — Overall coverage and quality assessment
- Biggest gaps — The riskiest untested code
- Top 5 tests to write first — Highest impact, with brief descriptions
- Test quality issues — Problems with existing tests that need fixing
- CI recommendations — Coverage thresholds, pre-commit hooks, reporting
- What's done well — Good testing practices already in place to maintain
1---2name: test-coverage3description: Analyzes test coverage gaps, identifies untested code paths, prioritizes which tests to write based on risk, and helps improve overall test quality. Use when the user says "what's not tested?", "check test coverage", "what tests are missing?", "improve coverage", or "are my tests good enough?".4---56# Test Coverage Analysis Skill78When analyzing test coverage, follow this structured process. The goal is not 100% coverage — it's ensuring the riskiest code is tested well.910## 1. Discover the Testing Setup1112Before analyzing, understand the project's testing landscape:13```bash14# Detect testing framework15# Node.js16cat package.json | grep -E "jest|vitest|mocha|ava|tap|playwright|cypress|testing-library"1718# Python19cat requirements.txt pyproject.toml setup.cfg 2>/dev/null | grep -E "pytest|unittest|nose|coverage|tox"2021# Ruby22cat Gemfile 2>/dev/null | grep -E "rspec|minitest|capybara|factory_bot"2324# Go25grep -r "_test.go" --include="*.go" -l .2627# Java28cat pom.xml build.gradle 2>/dev/null | grep -E "junit|mockito|testng|jacoco"2930# PHP31cat composer.json 2>/dev/null | grep -E "phpunit|pest|mockery"32```3334Identify:35- **Testing framework** in use (Jest, Vitest, Pytest, RSpec, JUnit, etc.)36- **Coverage tool** configured (Istanbul/nyc, coverage.py, SimpleCov, JaCoCo, etc.)37- **Test directory structure** (co-located vs separate test folder)38- **Naming conventions** (*.test.ts, *.spec.ts, test_*.py, *_test.go)39- **Test types present** (unit, integration, e2e, snapshot)40- **CI integration** (are tests running in CI? is coverage enforced?)4142## 2. Run Existing Coverage43```bash44# Node.js (Jest)45npx jest --coverage --coverageReporters=text4647# Node.js (Vitest)48npx vitest run --coverage4950# Python (Pytest)51python -m pytest --cov=. --cov-report=term-missing5253# Go54go test -coverprofile=coverage.out ./...55go tool cover -func=coverage.out5657# Ruby (RSpec)58COVERAGE=true bundle exec rspec5960# Java (Maven + JaCoCo)61mvn test jacoco:report6263# PHP (PHPUnit)64php artisan test --coverage65```6667Record:68- **Overall line coverage percentage**69- **Overall branch coverage percentage**70- **Files with 0% coverage** (completely untested)71- **Files with < 50% coverage** (poorly tested)72- **Uncovered lines** (specific line numbers)7374## 3. Identify What's NOT Tested7576### 3a. Find Files Without Tests77```bash78# Node.js — find source files without matching test files79find src -name "*.ts" -o -name "*.js" | while read f; do80 base=$(basename "$f" | sed 's/\.\(ts\|js\)$//')81 if ! find . -name "${base}.test.*" -o -name "${base}.spec.*" | grep -q .; then82 echo "NO TEST: $f"83 fi84done8586# Python — find modules without test files87find src -name "*.py" ! -name "__init__.py" | while read f; do88 base=$(basename "$f" .py)89 if ! find . -name "test_${base}.py" -o -name "${base}_test.py" | grep -q .; then90 echo "NO TEST: $f"91 fi92done9394# Go — find packages without test files95find . -name "*.go" ! -name "*_test.go" -exec dirname {} \; | sort -u | while read d; do96 if ! ls "$d"/*_test.go 2>/dev/null | grep -q .; then97 echo "NO TEST: $d"98 fi99done100```101102### 3b. Find Untested Code Paths103104Look for these commonly missed patterns:105106- **Error handlers and catch blocks** — the most commonly untested code107- **Edge cases** — null, undefined, empty arrays, zero, negative numbers, boundary values108- **Else branches** — the unhappy path in if/else109- **Switch default cases** — fallback handling110- **Early returns and guard clauses** — validation at the top of functions111- **Timeout and retry logic** — what happens when things fail112- **Race conditions** — concurrent operations113- **Cleanup code** — finally blocks, destructors, shutdown handlers114- **Configuration branches** — code that runs differently per environment115- **Deprecated or feature-flagged code** — code behind flags that's still reachable116117### 3c. Find Dead or Unreachable Code118```bash119# Node.js — find unused exports120npx ts-prune121122# Python — find unused code123pip install vulture && vulture src/124125# General — find functions not referenced anywhere126grep -rn "function\|def\|func " src/ | while read line; do127 fname=$(echo "$line" | grep -oP '(?:function|def|func)\s+\K\w+')128 count=$(grep -rn "$fname" src/ | wc -l)129 if [ "$count" -le 1 ]; then130 echo "POSSIBLY UNUSED: $line"131 fi132done133```134135## 4. Risk-Based Prioritization136137Not all untested code is equally important. Prioritize by risk:138139### 🔴 Critical — Test These First140- **Authentication and authorization** — login, signup, password reset, permission checks141- **Payment and billing** — charge, refund, subscription logic142- **Data mutation** — create, update, delete operations143- **API endpoints** — especially public-facing ones144- **Input validation** — sanitization and parsing of user input145- **Security-sensitive code** — encryption, token generation, access control146- **Core business logic** — the main value of your application147148### 🟠 High — Test These Next149- **Error handling** — catch blocks, error boundaries, fallback behavior150- **Database queries** — complex queries, transactions, migrations151- **Third-party integrations** — API calls, webhooks, callbacks152- **State management** — reducers, stores, state transitions153- **File operations** — uploads, downloads, processing154- **Background jobs** — queues, cron jobs, workers155156### 🟡 Medium — Test When Possible157- **UI components** — interactive components, forms, modals158- **Utility functions** — helpers, formatters, transformers159- **Configuration** — environment-specific logic160- **Middleware** — request/response processing pipeline161- **Caching logic** — cache invalidation, TTL, fallbacks162163### 🟢 Low — Test If Time Permits164- **Static components** — presentational components with no logic165- **Type definitions** — interfaces, types, enums166- **Constants and config objects** — static values167- **Logging** — log formatting and output168- **Dev-only code** — seeders, fixtures, debug utilities169170## 5. Test Quality Analysis171172Coverage percentage alone doesn't mean tests are good. Analyze quality:173174### Assertion Quality175```176// 🔴 BAD — test runs but asserts nothing meaningful177test('creates user', async () => {178 const result = await createUser({ name: 'Alice' });179 expect(result).toBeTruthy(); // too vague180});181182// ✅ GOOD — specific, meaningful assertions183test('creates user with correct fields', async () => {184 const result = await createUser({ name: 'Alice' });185 expect(result.id).toBeDefined();186 expect(result.name).toBe('Alice');187 expect(result.createdAt).toBeInstanceOf(Date);188});189```190191### Test Independence192```193// 🔴 BAD — tests depend on each other's state194let userId;195test('creates user', async () => {196 const user = await createUser({ name: 'Alice' });197 userId = user.id;198});199test('fetches user', async () => {200 const user = await getUser(userId); // depends on previous test201});202203// ✅ GOOD — each test sets up its own state204test('fetches user', async () => {205 const created = await createUser({ name: 'Alice' });206 const fetched = await getUser(created.id);207 expect(fetched.name).toBe('Alice');208});209```210211### Common Test Smells212- **No assertions** — test runs code but checks nothing213- **Testing implementation, not behavior** — brittle tests that break on refactors214- **Over-mocking** — mocking so much that the test proves nothing215- **Flaky tests** — tests that pass/fail randomly (timing, order-dependent, network)216- **Duplicate tests** — same scenario tested multiple times in different places217- **Giant test files** — 1000+ line test files that are hard to maintain218- **Missing cleanup** — tests that leave behind state (DB records, files, env vars)219- **Snapshot overuse** — snapshots accepted without review, hiding regressions220- **Copy-paste tests** — duplicated setup that should be extracted into helpers221- **Happy path only** — only testing success, never failure222223## 6. Stack-Specific Checks224225### Node.js / Jest / Vitest226- Check for missing `afterEach` cleanup (open handles, DB connections)227- Verify async tests use `await` or return promises (silent failures otherwise)228- Check for missing `jest.mock()` cleanup between tests229- Look for `setTimeout` in tests without `jest.useFakeTimers()`230- Verify snapshot tests are intentional and reviewed231- Check for missing error boundary tests in React components232- Verify `act()` wrapping on React state updates in tests233- Look for missing `waitFor` / `findBy` on async UI updates234235### Python / Pytest236- Check for missing `conftest.py` fixtures for common setup237- Verify database tests use transactions and rollback (`@pytest.mark.django_db`)238- Look for missing `parametrize` on tests that should cover multiple inputs239- Check for missing `mock.patch` cleanup (use context managers or decorators)240- Verify async tests use `@pytest.mark.asyncio`241- Check for missing exception tests (`with pytest.raises(...)`)242- Look for hardcoded file paths in tests (use `tmp_path` fixture)243- Verify test isolation — no tests reading/writing shared state244245### React / Next.js246- Check for missing `render` tests on all user-facing components247- Verify form components test validation, submission, and error states248- Look for missing accessibility tests (`@testing-library/jest-dom` matchers)249- Check for untested loading and error states250- Verify hooks are tested with `renderHook` from testing-library251- Check for missing tests on context providers and consumers252- Look for untested route guards and redirects253- Verify Server Components have integration tests254- Check for missing tests on API routes / Server Actions255256### Vue / Nuxt257- Check for missing `mount` / `shallowMount` tests on components258- Verify Pinia stores are tested with `createTestingPinia`259- Look for missing `emitted()` checks on event emissions260- Check for untested computed properties and watchers261- Verify composables are tested independently262- Check for missing tests on Nuxt middleware and plugins263264### Go265- Check for missing table-driven tests on functions with multiple inputs266- Verify error return values are tested (not just happy path)267- Look for missing `t.Parallel()` on independent tests268- Check for missing `t.Helper()` on test utility functions269- Verify interfaces are tested with mock implementations270- Check for missing benchmark tests on performance-critical code (`func BenchmarkX`)271- Look for missing `t.Cleanup()` for resource teardown272- Verify HTTP handlers are tested with `httptest.NewServer`273274### Java / Spring Boot275- Check for missing `@SpringBootTest` integration tests276- Verify `@MockBean` is used appropriately (not over-mocked)277- Look for missing `@Transactional` on database tests (auto rollback)278- Check for missing controller tests with `MockMvc`279- Verify exception handlers are tested280- Check for missing `@ParameterizedTest` on multi-input tests281- Look for untested `@Scheduled` tasks and async methods282- Verify repository custom queries have integration tests283284### Ruby / RSpec285- Check for missing `describe` blocks for each public method286- Verify `let` and `before` blocks handle proper setup/teardown287- Look for missing `context` blocks for different scenarios288- Check for missing `shared_examples` for common behavior289- Verify factory definitions cover all required fields (`FactoryBot`)290- Check for missing request specs on API endpoints291- Look for untested ActiveRecord callbacks and validations292- Verify background jobs (Sidekiq/Resque) have specs293294### PHP / Laravel295- Check for missing Feature tests on routes and controllers296- Verify database tests use `RefreshDatabase` or `DatabaseTransactions`297- Look for missing tests on form requests (validation rules)298- Check for missing `assertDatabaseHas` / `assertDatabaseMissing` assertions299- Verify mail, notification, and event fakes are used300- Check for missing tests on Eloquent scopes and accessors301- Look for untested middleware302- Verify queue jobs and listeners have tests303304### Mobile (React Native / Flutter)305- Check for missing widget/component tests306- Verify navigation flows are tested307- Look for missing tests on platform-specific code (iOS vs Android)308- Check for untested offline/error states309- Verify async storage operations are tested310- Check for missing tests on deep link handling311- Look for untested permission request flows312- Verify API response parsing is tested with realistic mock data313314### API / Integration Tests315- Check for missing tests on all HTTP methods (GET, POST, PUT, DELETE, PATCH)316- Verify authentication is tested (valid token, expired token, no token, wrong role)317- Look for missing tests on pagination, filtering, and sorting318- Check for missing tests on rate limiting behavior319- Verify webhook handlers are tested with realistic payloads320- Check for missing tests on file upload/download endpoints321- Look for untested CORS behavior322- Verify error responses match API documentation/contract323324### Database325- Check for missing migration tests (up and rollback)326- Verify complex queries are tested with realistic data volumes327- Look for missing tests on database constraints (unique, foreign key, check)328- Check for untested transaction behavior (commit, rollback, deadlock)329- Verify connection pooling and timeout handling is tested330- Check for missing seed data validation tests331332## 7. Coverage Improvement Plan333334After analysis, provide a prioritized plan:335336### Immediate (This Sprint)337- List specific files and functions to test first based on risk338- Provide test scaffolding for the highest-priority untested code339- Suggest specific test cases with descriptions340341### Short-Term (Next 2 Sprints)342- Increase coverage on medium-risk areas343- Add integration tests for critical user flows344- Fix test quality issues (weak assertions, flaky tests)345346### Long-Term (This Quarter)347- Set up coverage thresholds in CI (fail build if coverage drops)348- Add e2e tests for critical user journeys349- Implement mutation testing to verify test effectiveness350- Set up coverage trend tracking351352## Output Format353354### Coverage Report355356**Overall Coverage:**357| Metric | Current | Target | Gap |358|--------|---------|--------|-----|359| Line Coverage | X% | 80% | X% |360| Branch Coverage | X% | 70% | X% |361| Function Coverage | X% | 85% | X% |362363**Untested Files (by risk):**364365🔴 **Critical — No Tests:**366- `src/auth/login.ts` — handles user authentication367- `src/payments/charge.ts` — processes payments368369🟠 **High — Partial Coverage:**370- `src/api/users.ts` — 40% covered, missing error paths371- `src/db/queries.ts` — 55% covered, missing edge cases372373**Test Quality Issues:**374- `tests/user.test.ts:45` — assertion too vague (`toBeTruthy`)375- `tests/order.test.ts` — tests are order-dependent376- `tests/api.test.ts:120` — over-mocked, not testing real behavior377378### For Each Untested Area379380**File: `src/auth/login.ts`**381- **Risk**: 🔴 Critical382- **Why it matters**: Handles user authentication — bugs here = security breach383- **Missing tests**:384 1. Valid login with correct credentials385 2. Login with wrong password (should return 401)386 3. Login with non-existent email (should return 401, same message as wrong password)387 4. Login with expired account388 5. Rate limiting after 5 failed attempts389 6. SQL injection attempt in email field390 7. Session creation and token generation391- **Test scaffold**:392```393describe('login', () => {394 it('returns a token for valid credentials', async () => { ... });395 it('returns 401 for incorrect password', async () => { ... });396 it('returns 401 for non-existent email', async () => { ... });397 it('locks account after 5 failed attempts', async () => { ... });398 it('rejects SQL injection in email', async () => { ... });399});400```401402## Summary403404End every analysis with:4051. **Current state** — Overall coverage and quality assessment4062. **Biggest gaps** — The riskiest untested code4073. **Top 5 tests to write first** — Highest impact, with brief descriptions4084. **Test quality issues** — Problems with existing tests that need fixing4095. **CI recommendations** — Coverage thresholds, pre-commit hooks, reporting4106. **What's done well** — Good testing practices already in place to maintain