Coverage providers: v8 and istanbul
Vitest supports Native code coverage via v8 and instrumented code coverage via istanbul. Both are optional, and by default v8 is used. Set test.coverage.provider to 'v8' or 'istanbul' in vitest.config.ts. When the Vitest process starts, it will prompt you to install the corresponding support package automatically. Manual installation: npm i -D @vitest/coverage-v8 for v8, or npm i -D @vitest/coverage-istanbul for istanbul.
V8 coverage provider characteristics
V8 is the default provider in Vitest. It requires a JavaScript runtime implemented on top of V8 engine, such as NodeJS, Deno, or Chromium-based browsers. Coverage is collected during runtime via node:inspector and Chrome DevTools Protocol in browsers. User source files execute as-is without pre-instrumentation. Advantages: recommended, no pre-transpile step, faster execution than Istanbul, lower memory usage, coverage accuracy equals Istanbul since Vitest v3.2.0. Disadvantages: can be slower in some cases when loading many modules; has minor limitations from V8 engine; does not work on Firefox, Bun, or environments that don't expose V8 coverage like Cloudflare Workers.
Istanbul coverage provider characteristics
Istanbul has existed since 2012 and is battle-tested. Coverage tracking works by transforming source code to add instrumentation logic that tracks branch and function coverage at runtime. Advantages: works on any JavaScript runtime, widely used and battle-tested for over 13 years, in some cases faster than V8 when instrumentation is limited to specific files. Disadvantages: source code is transformed before running (adding instrumentation overhead), slower execution than V8, higher memory usage than V8.
Enable coverage in tests
To run tests with coverage enabled, pass the --coverage flag in CLI or set coverage.enabled to true in vitest.config.ts. Example package.json script: "coverage": "vitest run --coverage". Example vitest.config.ts: export default defineConfig({ test: { coverage: { enabled: true } } })
Coverage include and exclude patterns
Configure coverage.include and coverage.exclude in vitest.config.ts to control which files appear in coverage reports. By default, Vitest shows only files imported during test run. To include uncovered files, set coverage.include with a glob pattern matching source files (e.g., 'src/**/*.{ts,tsx}'). Use coverage.exclude to omit files matching the include pattern (e.g., '**/utils/users.ts').
Custom coverage reporters configuration
Pass custom coverage reporters in test.coverage.reporter as either an NPM package name or absolute path. Format: reporter: [['@vitest/custom-coverage-reporter', { someOption: true }], '/absolute/path/to/custom-reporter.cjs']. Custom reporters are loaded by Istanbul and must match its reporter interface. Reporters extend ReportBase and implement onStart(root, context) and onEnd() methods.
Custom coverage provider setup
Set test.coverage.provider to 'custom' and specify test.coverage.customProviderModule as a module name or path. The module must export an object implementing CoverageProviderModule as default export. The module must have a getProvider() method returning a CoverageProvider instance. The CoverageProvider class must have name, options, and initialize(ctx: Vitest) properties/methods, plus other required implementations.
V8 coverage AST-based remapping
Since Vitest v3.2.0, V8 coverage uses AST-based coverage remapping that produces identical coverage reports to Istanbul. This allows users to have the speed of V8 coverage with the accuracy of Istanbul coverage.
Ignoring code in coverage reports
Both v8 and istanbul have their own ways to ignore code from coverage reports. When using TypeScript, esbuild strips comments from source code, so you must use the @preserve keyword in ignore hints to keep them preserved. Examples: /* istanbul ignore if -- @preserve */ or /* v8 ignore if -- @preserve */. Both providers support ignore start/stop, if/else conditions, next node, try/catch, switch cases, and whole file ignoring.
V8 ignore code examples
V8 supports multiple ignore patterns:
- /* v8 ignore start -- @preserve */ ... /* v8 ignore stop -- @preserve */ for multi-line blocks
- /* v8 ignore if -- @preserve */ to ignore if-branch
- /* v8 ignore else -- @preserve */ to ignore else-branch
- /* v8 ignore next -- @preserve */ to ignore next statement, function, class, or ternary expression
- /* v8 ignore file -- @preserve */ to ignore entire file
For try-catch, /* v8 ignore next -- @preserve */ before catch (error) requires rolldown-vite due to esbuild limitation.
Coverage UI integration
Check coverage reports in Vitest UI and HTML reporter. Integration works out of the box with builtin coverage reporters that have HTML output (html, html-spa, lcov). The html reporter is enabled by default. To integrate with custom reporters, configure coverage.htmlDir.
Coverage in agent environments
When Vitest detects it is running inside an AI coding agent, it automatically adjusts the default text reporter: skipFull is set to true on the text reporter so files with 100% coverage are omitted from output, and the text-summary reporter is added automatically for a concise totals table. These adjustments only apply when the text reporter is already part of the active reporter list and do not remove explicitly configured reporters.
Coverage with v8 or istanbul
Vitest supports Native code coverage via v8 and instrumented code coverage via istanbul. Run with vitest run --coverage to generate coverage reports.
Compile cache disabled with v8 coverage provider
Vitest automatically disables the compile cache in workers when the v8 coverage provider is enabled — V8 serializes cached scripts without the source positions that precise coverage relies on.
Profile code coverage performance with DEBUG environment variable
Enable performance logging for code coverage generation using the DEBUG environment variable:
```bash
DEBUG=vitest:coverage vitest --run --coverage
```
This shows timing for each file conversion, identifies files taking longer than 3 seconds, and helps detect large files accidentally included in coverage.
Pitfall: Large files accidentally included in code coverage
Code coverage can be slow if large built minified JavaScript files are accidentally picked up. Use DEBUG=vitest:coverage to identify files taking longer than 3 seconds, then adjust coverage.include and coverage.exclude configuration options to exclude unnecessary files.