Claude Code Vitest Coverage Reporting (2026)
Automated test coverage reporting is essential for maintaining code quality in modern development workflows. This tutorial shows you how to integrate Vitest coverage reporting into your Claude Code projects, enabling automated quality checks and comprehensive reporting for your test suites.
Why Coverage Reporting Matters
Code coverage metrics help you understand how much of your codebase is exercised by tests. While 100% coverage doesn’t guarantee bug-free code, it identifies areas that lack testing attention. When working with Claude Code, you can automate these checks to catch regressions early and maintain consistent quality standards across your project.
There are four core metrics to understand before configuring anything:
- Statement coverage. the percentage of executable statements that were run during tests
- Branch coverage. whether both sides of conditional logic (if/else, ternary, switch cases) have been tested
- Function coverage. the percentage of declared functions that were called by any test
- Line coverage. similar to statement coverage but counted per line rather than per expression
In practice, branch coverage is the hardest to achieve and the most revealing. A function that appears fully covered by statement metrics can still have untested error paths, edge cases in conditionals, or fallback logic that only triggers under specific runtime conditions. Starting with branch coverage as your primary threshold gives you the most honest signal about test quality.
Setting Up Vitest with Coverage
First, ensure you have Vitest installed in your project. If you’re starting fresh, initialize a new project with the necessary dependencies:
npm create vitest@latest my-project -- --template vanilla-ts
cd my-project
npm install
Next, install a coverage provider. Vitest supports multiple providers, with V8 and Istanbul being the most popular:
npm install -D @vitest/coverage-v8
If you prefer Istanbul (which has stronger compatibility with older code patterns and supports more granular source mapping), install that instead:
npm install -D @vitest/coverage-istanbul
V8 vs Istanbul: Choosing a Coverage Provider
The choice between V8 and Istanbul depends on your project type:
| Feature | V8 | Istanbul |
|---|---|---|
| Speed | Faster (native engine) | Slower (instrumentation-based) |
| Source map accuracy | Good for modern TS | Better for transpiled code |
| CJS/ESM support | ESM-first | Both |
| Setup complexity | Minimal | Minimal |
| Reports generated | Standard set | Standard set + lcov |
For most TypeScript projects using ESM modules, V8 is the right default. If you’re working with CommonJS modules, Babel transforms, or older codebases, Istanbul tends to produce more accurate results because it works at the source level rather than relying on runtime engine instrumentation.
Configuring Coverage in Vitest
Create or update your vitest.config.ts to include coverage settings. This configuration enables coverage collection and specifies which files to include:
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
reportsDirectory: './coverage',
include: ['src//*.{ts,tsx}'],
exclude: ['src//*.d.ts', 'src/main.ts'],
thresholds: {
lines: 80,
functions: 80,
branches: 75,
statements: 80
}
}
}
})
The thresholds configuration ensures your project maintains minimum coverage standards. If coverage drops below these values, tests will fail, a useful gate for pull requests and CI pipelines.
Beyond the basics, several additional options are worth knowing:
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html', 'lcov'],
reportsDirectory: './coverage',
include: ['src//*.{ts,tsx}'],
exclude: [
'src//*.d.ts',
'src/main.ts',
'src//__mocks__/',
'src//types/',
'src//*.stories.{ts,tsx}'
],
// Don't fail the run if no files match the include pattern
skipFull: false,
// Show all files even if they have 0% coverage
all: true,
thresholds: {
lines: 80,
functions: 80,
branches: 75,
statements: 80
}
}
}
})
The all: true option is important. Without it, Vitest only reports coverage for files that were actually imported during tests. Files that exist in src/ but have no tests at all won’t appear in the report. Setting all: true exposes those hidden gaps.
Running Coverage Reports
Execute coverage reports using the --coverage flag:
npx vitest run --coverage
This generates reports in multiple formats. The text reporter shows summary output in your terminal:
---------------------------|---------|----------|---------|---------|
File | % Stmts | % Branch | % Funcs | % Lines |
---------------------------|---------|----------|---------|---------|
src/utils.ts | 90.12 | 85.71 | 100.00 | 89.47 |
src/calculator.ts | 78.34 | 66.66 | 85.00 | 77.27 |
---------------------------|---------|----------|---------|---------|
For detailed analysis, open the HTML report at coverage/index.html in your browser.
The HTML report is significantly more useful than the terminal summary. It lets you click into individual files and see exactly which lines were hit (green), which were missed (red), and which branches were only partially covered (yellow). Use the HTML report when you’re investigating why a file has lower-than-expected branch coverage, the visual diff is far faster than reading logs.
When running coverage during development, use watch mode to see coverage update as you write tests:
npx vitest --coverage --reporter=verbose
This keeps the test runner active and reruns affected tests on file save, showing updated coverage after each change. The feedback loop is much tighter than running vitest run manually after every change.
Integrating with Claude Code
Claude Code can help you maintain coverage standards by running tests and analyzing results. Create a simple skill that runs coverage and reports findings:
---
name: Run Coverage Check
description: Execute Vitest coverage report and analyze results
---
Run the Vitest coverage report using:
`npx vitest run --coverage`
After completion, read the coverage summary from the output. Identify any files or modules below the 80% threshold. Provide specific recommendations for improving coverage in under-tested areas.
This workflow helps you identify coverage gaps quickly. You can extend this pattern to automatically comment on pull requests or fail builds when coverage drops.
Beyond just running coverage, Claude Code can interpret results and suggest specific tests. A productive workflow looks like this:
- Run
npx vitest run --coverageand share the output with Claude Code - Point Claude to specific files with low branch coverage
- Ask Claude to read those files and generate tests targeting the uncovered branches
- Run coverage again to confirm the new tests hit the targeted code
Claude is especially effective at identifying branches that are hard to test without mocking. for example, error handling paths that only execute when a network call fails, or conditional logic gated behind environment variables. When you share the coverage HTML output or the JSON summary file, Claude can cross-reference it against the source and propose targeted tests.
Automating in Continuous Integration
CI integration ensures coverage checks run on every code change. Here’s a GitHub Actions workflow that runs Vitest coverage:
name: Test Coverage
on: [push, pull_request]
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npx vitest run --coverage
- uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
This workflow runs coverage on every push and pull request, uploading the HTML report as an artifact you can download and review.
For teams that want coverage data visible in pull request comments, extend the workflow to post a summary:
name: Test Coverage
on:
pull_request:
types: [opened, synchronize]
jobs:
coverage:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npx vitest run --coverage --reporter=json
- name: Post coverage comment
uses: davelosert/vitest-coverage-report-action@v2
with:
json-summary-path: coverage/coverage-summary.json
The vitest-coverage-report-action reads the JSON summary file and posts a formatted table as a PR comment. Reviewers can see at a glance whether a PR increases or decreases coverage without downloading artifacts.
Setting Up Coverage Thresholds
Effective threshold configuration balances code quality with practical development velocity. Start with achievable targets and gradually increase them:
export default defineConfig({
test: {
coverage: {
thresholds: {
lines: 70,
functions: 70,
branches: 65,
statements: 70,
// Per-file thresholds for critical modules
'src/core/': {
lines: 90,
branches: 85
}
}
}
}
})
Per-file thresholds are particularly useful for critical modules like authentication, payment processing, or core business logic where you need stricter testing requirements.
A phased approach to thresholds works well for teams inheriting an existing codebase without coverage infrastructure:
Phase 1 (first two weeks): Set thresholds at your current coverage level. Run coverage once, note the current percentages, and set those as the floor. This prevents regression while giving developers time to add tests without immediately blocking CI.
Phase 2 (weeks 3-6): Raise thresholds by 5 percentage points per metric. Focus new tests on areas with the highest risk. recently changed files and modules handling external I/O.
Phase 3 (ongoing): Set target thresholds for production code (80-90% line coverage, 75-80% branch coverage) and apply per-file overrides for legacy modules you plan to rewrite rather than test.
This avoids the common failure mode of setting 80% thresholds on a project at 40% and watching CI block every PR for months.
Generating Coverage Badges
Coverage badges communicate quality standards at a glance. After running coverage, generate badges using tools like coverage-badges:
npm install -D coverage-badges
npx vitest run --coverage
npx coverage-badges --input ./coverage/coverage-summary.json
Upload the generated SVG to your repository or documentation. Many CI platforms also support coverage badges directly through their interfaces.
For projects hosted on GitHub, Codecov and Coveralls both integrate with Vitest’s LCOV output and provide hosted badge URLs:
In your GitHub Actions workflow
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
files: ./coverage/lcov.info
fail_ci_if_error: false
Make sure your Vitest config includes 'lcov' in the reporters array when using these services. The LCOV format is the standard input they expect.
Best Practices for Coverage Workflows
Follow these practices to make coverage reporting effective:
Run coverage locally before pushing. Catch coverage issues locally rather than waiting for CI feedback. Add a script to your package.json for quick local checks:
{
"scripts": {
"test:coverage": "vitest run --coverage",
"test:ci": "vitest run --coverage && npx coverage-badges"
}
}
Review coverage reports in code reviews. When Claude Code assists with reviews, include coverage analysis in the feedback. This helps team members understand testing gaps in their changes.
Track coverage trends over time. Store coverage metrics in your monitoring system or as build artifacts. Declining coverage often indicates technical debt accumulating in untested areas.
Exclude generated and boilerplate code from coverage. Auto-generated files, type definition stubs, Storybook stories, and migration scripts should be excluded. Including them distorts your metrics and creates pressure to write tests for code that doesn’t need them.
Treat coverage as a diagnostic, not a goal. High coverage with weak assertions is worse than moderate coverage with precise assertions. Tests that import a module and call every function without asserting any behavior will boost your numbers while providing no protection against regressions. When Claude Code generates tests, always review the assertions. not just the coverage percentage.
Use coverage to find missing error paths. The most valuable use of branch coverage is finding uncovered catch blocks, fallback returns, and early exits. These paths are easy to forget during initial development and frequently contain bugs that only appear under production conditions.
Conclusion
Integrating Vitest coverage reporting with Claude Code creates a powerful quality assurance workflow. The combination of automated testing, clear threshold enforcement, and actionable reporting helps teams maintain high code quality standards. Start with reasonable thresholds, integrate coverage checks into your CI pipeline, and gradually tighten requirements as your test suite matures.
With these practices in place, you’ll have visibility into your code’s test coverage and be able to make informed decisions about where to focus testing efforts next. Coverage reporting is most useful when it’s fast, automatic, and visible. once those three conditions are met, the metrics start shaping how your team thinks about writing code, not just testing it.
Try it: Paste your error into our Error Diagnostic for an instant fix.
Related Reading
- Jest to Vitest Migration Workflow with Claude Code
- Claude Code Coverage Reporting Setup Guide
- Claude Code for Evals Framework Workflow Tutorial
Built by theluckystrike. More at zovo.one
Get started → Generate your project setup with our Project Starter.