Skip to content

Commit

Permalink
almost working coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Sep 10, 2022
1 parent 83da92a commit 26447d7
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 7 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
},
"dependencies": {
"@jest/expect": "^29.0.1",
"@jest/transform": "^29.0.1",
"collect-v8-coverage": "^1.0.1",
"jest-circus": "^29.0.1",
"jest-each": "^29.0.1",
"jest-mock": "^29.0.1",
Expand Down
57 changes: 53 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { Piscina } from "piscina";
import supportsColor from "supports-color";
import { MessageChannel } from "worker_threads";
import { shouldInstrument } from "@jest/transform";
import { fileURLToPath } from "url";

/** @typedef {import("@jest/test-result").Test} Test */

export default class LightRunner {
// TODO: Use real private fields when we drop support for Node.js v12
_config;
_piscina;
_testContext;

constructor(config) {
constructor(config, testContext) {
this._config = config;
this._testContext = testContext;

// Jest's logic to decide when to spawn workers and when to run in the
// main thread is quite complex:
Expand All @@ -36,6 +40,36 @@ export default class LightRunner {
});
}

filterCoverage(result, projectConfig) {
if (!result.v8Coverage) {
return result;
}

const coverageOptions = {
changedFiles: this._testContext.changedFiles,
collectCoverage: true,
collectCoverageFrom: this._config.collectCoverageFrom,
collectCoverageOnlyFrom: this._config.collectCoverageOnlyFrom,
coverageProvider: this._config.coverageProvider,
sourcesRelatedToTestsInChangedFiles:
this._testContext.sourcesRelatedToTestsInChangedFiles,
};

return {
...result,
v8Coverage: result.v8Coverage
.filter(res => res.url.startsWith("file://"))
.map(res => ({ ...res, url: fileURLToPath(res.url) }))
.filter(
({ url }) =>
// TODO: will this work on windows? It might be better if `shouldInstrument` deals with it anyways
url.startsWith(projectConfig.rootDir) &&
shouldInstrument(url, coverageOptions, projectConfig)
)
.map(result => ({ result })),
};
}

/**
* @param {Array<Test>} tests
* @param {*} watcher
Expand All @@ -44,7 +78,12 @@ export default class LightRunner {
* @param {*} onFailure
*/
runTests(tests, watcher, onStart, onResult, onFailure) {
const { updateSnapshot, testNamePattern } = this._config;
const {
updateSnapshot,
testNamePattern,
collectCoverage,
coverageProvider,
} = this._config;

return Promise.all(
tests.map(test => {
Expand All @@ -54,11 +93,21 @@ export default class LightRunner {

return this._piscina
.run(
{ test, updateSnapshot, testNamePattern, port: mc.port1 },
{
test,
updateSnapshot,
testNamePattern,
port: mc.port1,
collectV8Coverage: collectCoverage && coverageProvider === "v8",
},
{ transferList: [mc.port1] }
)
.then(
result => void onResult(test, result),
result =>
void onResult(
test,
this.filterCoverage(result, test.context.config)
),
error => void onFailure(test, error)
);
})
Expand Down
20 changes: 18 additions & 2 deletions src/worker-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { expect } from "expect";
import * as circus from "jest-circus";
import { inspect } from "util";
import { isWorkerThread } from "piscina";
import { CoverageInstrumenter } from "collect-v8-coverage";

/** @typedef {{ failures: number, passes: number, pending: number, start: number, end: number }} Stats */
/** @typedef {{ ancestors: string[], title: string, duration: number, errors: Error[], skipped: boolean }} InternalTestResult */
Expand Down Expand Up @@ -54,6 +55,7 @@ export default async function run({
updateSnapshot,
testNamePattern,
port,
collectV8Coverage,
}) {
const projectSnapshotSerializers = await initialSetup(test.context.config);

Expand All @@ -67,6 +69,13 @@ export default async function run({
/** @type {Array<InternalTestResult>} */
const results = [];

let instrumenter = null;
if (collectV8Coverage) {
instrumenter = new CoverageInstrumenter();

await instrumenter.startInstrumenting();
}

const { tests, hasFocusedTests } = await loadTests(test.path);

const snapshotResolver = await snapshot.buildSnapshotResolver(
Expand All @@ -86,13 +95,18 @@ export default async function run({
await runTestBlock(tests, hasFocusedTests, testNamePatternRE, results, stats);
stats.end = performance.now();

let v8Coverage = undefined;
if (instrumenter) {
v8Coverage = await instrumenter.stopInstrumenting();
}

snapshotState.save();

// Restore the project-level serializers, so that serializers
// installed by one test file don't leak to other files.
arrayReplace(snapshot.getSerializers(), projectSnapshotSerializers);

return toTestResult(stats, results, test);
return toTestResult(stats, results, test, v8Coverage);
}

async function loadTests(testFile) {
Expand Down Expand Up @@ -236,9 +250,10 @@ function callAsync(fn) {
* @param {Stats} stats
* @param {Array<InternalTestResult>} tests
* @param {import("@jest/test-result").Test} testInput
* @param {import("@jest/test-result").V8CoverageResult} v8Coverage
* @returns {import("@jest/test-result").TestResult}
*/
function toTestResult(stats, tests, { path, context }) {
function toTestResult(stats, tests, { path, context }, v8Coverage) {
const { start, end } = stats;
const runtime = end - start;

Expand Down Expand Up @@ -285,6 +300,7 @@ function toTestResult(stats, tests, { path, context }) {
title: test.title,
};
}),
v8Coverage,
};
}

Expand Down
4 changes: 3 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1031,7 +1031,7 @@ __metadata:
languageName: node
linkType: hard

"collect-v8-coverage@npm:^1.0.0":
"collect-v8-coverage@npm:^1.0.0, collect-v8-coverage@npm:^1.0.1":
version: 1.0.1
resolution: "collect-v8-coverage@npm:1.0.1"
checksum: 4efe0a1fccd517b65478a2364b33dadd0a43fc92a56f59aaece9b6186fe5177b2de471253587de7c91516f07c7268c2f6770b6cbcffc0e0ece353b766ec87e55
Expand Down Expand Up @@ -1655,6 +1655,8 @@ __metadata:
resolution: "jest-light-runner@workspace:."
dependencies:
"@jest/expect": ^29.0.1
"@jest/transform": ^29.0.1
collect-v8-coverage: ^1.0.1
jest-circus: ^29.0.1
jest-each: ^29.0.1
jest-mock: ^29.0.1
Expand Down

0 comments on commit 26447d7

Please sign in to comment.