← All guides

Improve Test Coverage with Claude Code

How to use Claude Code to analyze coverage reports, generate targeted tests for uncovered branches, and go from 45% to 92% coverage in 30 minutes.

Improve Test Coverage with Claude Code

To improve test coverage with Claude Code, paste your coverage report directly into Claude and ask it to generate tests for every uncovered line and branch. Claude reads Jest, Vitest, and pytest --cov output, identifies exactly which code paths are untested, and writes targeted tests — including edge cases, mocks, and parameterized variants — without you needing to identify the gaps manually. A TypeScript project can move from 45% to 92% coverage in a single focused session.


Analyzing Coverage Reports

Before generating tests, get a machine-readable coverage report.

Jest / Vitest:

npx jest --coverage --coverageReporters=text-summary
# or for detailed per-file output:
npx jest --coverage --coverageReporters=lcov --coverageReporters=text

pytest:

pytest --cov=src --cov-report=term-missing --cov-report=json

The term-missing flag prints the exact uncovered line numbers — the format Claude understands best.

Prompt: feed the report to Claude Code

Here is my Jest coverage report:

[paste coverage output]

List every file below 80% branch coverage, show the uncovered branch ranges,
and generate a test file for each. Use the existing test style from
`src/__tests__/auth.test.ts` as the template.

Claude parses the coverage table, cross-references source files, and produces tests matched to your existing patterns. For a guide on the underlying test generation workflow, see Claude Code test generation.


Targeted Test Generation for Uncovered Branches

Coverage tools report line coverage and branch coverage separately. Branch coverage is harder to hit — every if, ternary, &&, and || creates two branches.

Prompt for branch-specific tests:

This function has 3 uncovered branches according to Istanbul:
- line 24: the `if (user.role === 'admin')` false branch
- line 31: the catch block
- line 45: the early return when `items.length === 0`

Generate Jest tests that trigger each uncovered branch.
Source file:

[paste the function]

Claude produces one describe block per uncovered branch, with assertions that verify the exact return value or side effect of each path.


Edge-Case Testing Patterns

High coverage numbers do not guarantee quality unless edge cases are covered. Use these prompts after hitting line/branch targets.

Boundary value prompt:

For the `calculateDiscount(price, quantity)` function, generate tests covering:
- price = 0, price = -1, price = Number.MAX_SAFE_INTEGER
- quantity = 0, quantity = 1, quantity = 1000
- all combinations where the result should round to zero

Null / undefined / type coercion prompt:

Generate tests for `parseUserInput(input)` that cover:
- null, undefined, empty string, whitespace-only string
- non-string types (number, object, array)
- strings with special characters: <, >, ", ', \, \n, \0

Async error paths:

The fetchOrders() function has no tests for network failures or timeout.
Generate tests using jest.spyOn to simulate:
- fetch throwing a network error
- fetch returning a 500 response
- fetch hanging past the 5000ms timeout

Mocking Strategies

Untested branches are often hidden behind external dependencies. Claude Code generates appropriate mocks when you specify the dependency type.

Module mock:

Generate a test for `sendWelcomeEmail(user)` that mocks the
`@sendgrid/mail` module. The test should verify the correct
template ID and recipient address without making real HTTP calls.

Spy / partial mock:

Generate a test for `UserService.createUser()` that spies on
`db.transaction` to verify it is called exactly once,
without mocking the entire db module.

Time mock:

Generate tests for `isSubscriptionExpired(user)` that mock
Date.now() to simulate a date 1 day before expiry,
on the expiry day, and 1 day after.

Integration vs Unit Balance

Claude Code can help you decide where to place new tests.

Rule of thumb Claude applies:

Prompt to classify your untested code:

Review these 12 uncovered functions from my coverage report
and categorize each as: unit test candidate, integration test candidate,
or skip (trivial getter/setter). Explain your reasoning.

[paste function signatures and line counts]

This prevents writing expensive integration tests for simple logic and avoids brittle unit tests for database code. See Claude agent testing and eval for how this scales to agent pipelines.


Mutation Testing

Mutation testing verifies that your tests actually catch bugs — not just execute code. Tools like Stryker (JavaScript) and mutmut (Python) introduce small code mutations and check if your tests fail.

Workflow with Claude Code:

# Run Stryker mutation report
npx stryker run
Here is my Stryker mutation report showing 14 surviving mutants:

[paste report]

For each surviving mutant, explain why the existing test missed it,
then add a new assertion that would kill it.

Surviving mutants indicate tests that assert the wrong thing or do not assert at all. Claude fixes them by strengthening the assertions rather than adding new test cases.


Real Workflow: 45% to 92% Coverage in 30 Minutes

Project: TypeScript REST API, 28 source files, 3,400 lines, Jest.

Starting state: 45% statement coverage, 38% branch coverage. No mock infrastructure.

Step 1 — Coverage report (2 min):

npx jest --coverage --coverageReporters=json-summary > coverage-summary.json
npx jest --coverage --coverageReporters=text 2>&1 | tee coverage-text.txt

Step 2 — Triage with Claude Code (5 min):

Read coverage-text.txt. List the 10 files with the lowest branch coverage.
For each, show: file path, current branch%, uncovered line ranges.

Output: 10 files, all below 50% branch coverage, concentrated in src/services/ and src/middleware/.

Step 3 — Generate mock infrastructure (8 min):

Create `src/__tests__/mocks/` with:
- db.mock.ts — jest.mock for our Prisma client
- mailer.mock.ts — jest.mock for nodemailer
- redis.mock.ts — jest.mock for ioredis
Match the pattern in src/__tests__/auth.test.ts

Step 4 — Generate service tests (10 min):

Using coverage-text.txt and the mocks in src/__tests__/mocks/,
generate test files for the 5 service files below 40% coverage.
Cover every uncovered branch. Use parameterized tests
where the same logic applies to multiple inputs.

Claude generated 340 lines of tests across 5 files.

Step 5 — Generate middleware tests (5 min):

Generate tests for src/middleware/rateLimit.ts and src/middleware/auth.ts.
The rate limit tests should mock Date.now() to simulate window resets.
The auth tests should cover expired tokens, malformed tokens, and missing headers.

Final result after 30 minutes:

Metric Before After
Statement coverage 45% 91%
Branch coverage 38% 92%
Test files added 0 7
New test cases 0 94

Cost breakdown (Claude Sonnet 4.5):

For the full Claude Code capability reference, see the Claude Code complete guide.


Gumroad CTA

Struggling to write the right prompts for your specific test framework or codebase?

Claude Code Power Prompts 300 includes 40+ testing prompts — for Jest, Vitest, pytest, and more — covering mock setup, branch coverage, mutation testing, and snapshot management. Copy, paste, and reach 80%+ coverage faster.

→ Get Claude Code Power Prompts 300 — $29

300 prompts. Instant download. 30-day money-back guarantee.


Snapshot Tests and Parameterized Tests

Snapshot tests catch unintended UI or serialization regressions.

Generate snapshot tests for the UserCard, OrderSummary, and InvoicePDF
React components. Each snapshot test should render the component
with realistic props pulled from our Faker fixtures in src/__tests__/fixtures/.

To update snapshots after intentional changes:

My snapshots are failing after the design update to UserCard.
Review the diff below, confirm the changes are intentional,
then update only the UserCard snapshot. Leave all others untouched.

[paste snapshot diff]

Parameterized tests reduce duplication when the same logic applies to many inputs.

Convert these 8 nearly-identical test cases for validateEmail()
into a single describe.each / it.each block.

[paste the 8 test cases]

Jest example output:

describe.each([
  ["valid@example.com", true],
  ["missing-at-sign.com", false],
  ["@no-local-part.com", false],
  ["spaces in@address.com", false],
  ["valid+tag@sub.domain.io", true],
])("validateEmail('%s')", (input, expected) => {
  it(`returns ${expected}`, () => {
    expect(validateEmail(input)).toBe(expected);
  });
});

Frequently Asked Questions

How do I get Claude Code to generate tests without breaking existing ones?

Tell Claude explicitly: "Do not modify existing test files. Create new test files only, using the naming convention *.spec.ts in the same directory as the source file." Claude respects this constraint and adds only additive test files.

What coverage percentage should I target?

80% branch coverage is the practical threshold for most production codebases. Going from 80% to 100% has diminishing returns and often produces brittle tests for trivial getters and framework boilerplate. Focus Claude on the business logic files — auth, payments, data transforms — rather than configuration files and type definitions.

Can Claude Code handle large source files that exceed its context window?

Yes, with chunking. Paste one function at a time rather than an entire file: "Here is the processPayment function (lines 45–120 of payments.ts). Generate tests for every branch." For systematic coverage of large files, use Claude Code's subagent parallel execution to process multiple functions simultaneously.

How do I make sure generated tests actually run and pass?

Add a step in your prompt: "After generating the tests, list any imports or fixtures that the tests depend on that do not exist yet." Claude will flag missing dependencies — mock files, fixture data, helper utilities — so you can create them before running the suite.

Does this work for Python projects with pytest?

Yes. Use pytest --cov=src --cov-report=term-missing to get line numbers, then paste the output. Ask Claude to generate pytest test functions using the same fixture patterns as your existing conftest.py. For parameterized Python tests, Claude uses @pytest.mark.parametrize automatically when it detects multiple similar inputs.


Take It Further

Want 300 ready-to-use prompts for every Claude Code workflow — including 40+ testing prompts?

Claude Code Power Prompts 300 covers mock setup, coverage triage, mutation testing, snapshot management, and CI integration. Every prompt is tested in production sessions and organized by use case.

→ Get Claude Code Power Prompts 300 — $29

Instant download. 30-day money-back guarantee.

Tools and references