Skip to content

Commit

Permalink
fix: collect coverage using node inspector (fix #378) (#584)
Browse files Browse the repository at this point in the history
  • Loading branch information
Demivan committed Jan 23, 2022
1 parent cf30e5a commit de33284
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 12 deletions.
7 changes: 2 additions & 5 deletions packages/vitest/src/coverage.ts
Expand Up @@ -95,7 +95,6 @@ export interface C8Options {
}

export interface ResolvedC8Options extends Required<C8Options> {
tempDirectory: string
}

export function resolveC8Options(options: C8Options, root: string): ResolvedC8Options {
Expand All @@ -116,17 +115,13 @@ export function resolveC8Options(options: C8Options, root: string): ResolvedC8Op

resolved.reporter = toArray(resolved.reporter)
resolved.reportsDirectory = resolve(root, resolved.reportsDirectory)
resolved.tempDirectory = process.env.NODE_V8_COVERAGE || resolve(resolved.reportsDirectory, 'tmp')

return resolved as ResolvedC8Options
}

export async function cleanCoverage(options: ResolvedC8Options, clean = true) {
if (clean && existsSync(options.reportsDirectory))
await fs.rm(options.reportsDirectory, { recursive: true, force: true })

if (!existsSync(options.tempDirectory))
await fs.mkdir(options.tempDirectory, { recursive: true })
}

const require = createRequire(import.meta.url)
Expand All @@ -136,6 +131,8 @@ export async function reportCoverage(ctx: Vitest) {
const createReport = require('c8/lib/report')
const report = createReport(ctx.config.coverage)

report._loadReports = () => ctx.coverage

const original = report._getMergedProcessCov

report._getMergedProcessCov = () => {
Expand Down
7 changes: 0 additions & 7 deletions packages/vitest/src/node/cli.ts
@@ -1,5 +1,4 @@
import cac from 'cac'
import { execa } from 'execa'
import type { UserConfig } from '../types'
import { version } from '../../package.json'
import { ensurePackageInstalled } from '../utils'
Expand Down Expand Up @@ -80,12 +79,6 @@ async function run(cliFilters: string[], options: UserConfig) {
if (ctx.config.coverage.enabled) {
if (!await ensurePackageInstalled('c8'))
process.exit(1)

if (!process.env.NODE_V8_COVERAGE) {
process.env.NODE_V8_COVERAGE = ctx.config.coverage.tempDirectory
const { exitCode } = await execa(process.argv0, process.argv.slice(1), { stdio: 'inherit' })
process.exit(exitCode)
}
}

if (ctx.config.environment && ctx.config.environment !== 'node') {
Expand Down
3 changes: 3 additions & 0 deletions packages/vitest/src/node/core.ts
@@ -1,4 +1,5 @@
import { existsSync } from 'fs'
import type { Profiler } from 'inspector'
import type { ViteDevServer } from 'vite'
import fg from 'fast-glob'
import mm from 'micromatch'
Expand All @@ -24,6 +25,7 @@ export class Vitest {
server: ViteDevServer = undefined!
state: StateManager = undefined!
snapshot: SnapshotManager = undefined!
coverage: Profiler.TakePreciseCoverageReturnType[] = []
reporters: Reporter[] = undefined!
console: Console
pool: WorkerPool | undefined
Expand Down Expand Up @@ -260,6 +262,7 @@ export class Vitest {
// })
// }
this.snapshot.clear()
this.coverage = []
const files = Array.from(this.changedTests)
this.changedTests.clear()

Expand Down
3 changes: 3 additions & 0 deletions packages/vitest/src/node/pool.ts
Expand Up @@ -111,6 +111,9 @@ function createChannel(ctx: Vitest) {
snapshotSaved(snapshot) {
ctx.snapshot.add(snapshot)
},
coverageCollected(coverage) {
ctx.coverage.push(coverage)
},
async getSourceMap(id, force) {
if (force) {
const mod = ctx.server.moduleGraph.getModuleById(id)
Expand Down
25 changes: 25 additions & 0 deletions packages/vitest/src/runtime/run.ts
@@ -1,4 +1,5 @@
import { performance } from 'perf_hooks'
import inspector from 'inspector'
import type { HookListener, ResolvedConfig, Suite, SuiteHooks, Task, TaskResult, Test } from '../types'
import { vi } from '../integrations/vi'
import { getSnapshotClient } from '../integrations/snapshot/chai'
Expand Down Expand Up @@ -188,8 +189,32 @@ export async function startTests(paths: string[], config: ResolvedConfig) {

rpc().onCollected(files)

let session!: inspector.Session
if (config.coverage.enabled) {
inspector.open(0)
session = new inspector.Session()
session.connect()

session.post('Profiler.enable')
session.post('Profiler.startPreciseCoverage', { detailed: true })
}

await runSuites(files)

if (config.coverage.enabled) {
session.post('Profiler.takePreciseCoverage', (_, coverage) => {
rpc().coverageCollected(coverage)
})

session.disconnect()
try {
inspector.close()
}
catch {
// Fails inside workers for some reason
}
}

await getSnapshotClient().saveSnap()

await sendTasksUpdate()
Expand Down
2 changes: 2 additions & 0 deletions packages/vitest/src/types/worker.ts
@@ -1,3 +1,4 @@
import type { Profiler } from 'inspector'
import type { MessagePort } from 'worker_threads'
import type { FetchFunction, ViteNodeResolveId } from 'vite-node'
import type { RawSourceMap } from '../types'
Expand Down Expand Up @@ -27,4 +28,5 @@ export interface WorkerRPC {
onTaskUpdate: (pack: TaskResultPack[]) => void

snapshotSaved: (snapshot: SnapshotResult) => void
coverageCollected: (coverage: Profiler.TakePreciseCoverageReturnType) => void
}

0 comments on commit de33284

Please sign in to comment.