Coverage¶
The Test Explorer's Coverage profile shows statement, branch and function coverage in the editor gutter
and the coverage view. Jest Runner does not instrument anything itself: it asks the framework for its usual
report, reads the report file and converts it to the VS Code coverage API. The code is
src/coverageProvider.ts with src/parsers/lcov-parser.ts.
Two report formats¶
| Format | Frameworks | File | Produced by |
|---|---|---|---|
Istanbul JSON (coverage-final.json) |
Jest, Vitest, Rstest | <coverage dir>/coverage-final.json |
--coverageReporters=json (Jest), --coverage.reporter json --coverage.reportOnFailure (Vitest), --coverage (Rstest) |
LCOV (lcov.info) |
Node.js, Bun, Deno | lcov.info or coverage/lcov.info |
the lcov test reporter (Node.js), --coverage-reporter=lcov (Bun), deno coverage coverage --lcov > lcov.info run by the executor (Deno) |
Playwright has no coverage support here.
Finding the report¶
readCoverageFromFile(workspaceFolder, framework, configPath?, testFilePath?):
- JSON frameworks: the coverage directory is, in order,
coverageDirectory/coverage.reportsDirectoryparsed from the config passed to the run (parseCoverageDirectory, relative torootDir/rootand the config's directory), the same from any config file of the framework in the workspace folder, elsecoverage/next to the config or in the workspace folder. The file must exist and not be empty ({}), or a hint is logged (Make sure you have ... configured with JSON reporter). - LCOV frameworks:
findLcovRecursivelystarts at the test file's directory (else the config's, else the workspace folder) and walks up to the workspace folder, checkinglcov.infoandcoverage/lcov.infoin each directory. Relative file names in the report are resolved against the report's directory.
For Bun, the executor deletes a stale coverage/lcov.info before the run, so an old report is never shown
when the new run fails to write one.
Converting¶
Istanbul JSON is already the internal CoverageMap shape (statementMap, fnMap, branchMap with their
hit counts s, f, b). LCOV is converted by processLcovRecord into the same shape: each DA line becomes
a statement spanning that line, each FN/FNDA a function, and the BRDA entries of one line one branch
group with one location per branch.
convertToVSCodeCoverage(map) then creates a DetailedFileCoverage per file, a subclass of
vscode.FileCoverage that carries the raw data, with summary counts: statements covered / total, branches
(all branch hits flattened), declarations (functions). Files under node_modules and files that match the
test patterns (matchesTestFilePattern) are left out, so the view shows the code under test only.
run.addCoverage(fileCoverage) hands the summaries to VS Code. When the user expands a file, the profile's
loadDetailedCoverage callback (wired in TestController) calls CoverageProvider.loadDetailedCoverage,
which builds the per-range details:
vscode.StatementCoverage(count, range)for every statement,vscode.DeclarationCoverage(name, count, range)for every function,vscode.StatementCoverage(max count, range, branches[])with onevscode.BranchCoverageper branch location for every branch group.
Lines and columns are converted from Istanbul's 1-based lines to VS Code's 0-based positions.
Where the Test Explorer calls it¶
TestRunExecutor.runStandardMode → processCoverageData(run, workspaceFolder, framework, configPath,
firstFile) after the test results, in a finally, so a failed result parse does not lose the coverage.
Fast mode is never used with coverage (canUseFastMode returns false), because the report must be read
after the run.
Terminal coverage¶
The coverage and current-test-coverage CodeLens actions and the two coverage commands only add
--coverage (and --collectCoverageFrom) to the terminal command. The framework prints its text summary and
writes its configured reporters; nothing is read back.