Skip to content

Commit 5da8384

Browse files
committed
test_runner: report coverage thresholds in test:coverage
1 parent b77476d commit 5da8384

File tree

4 files changed

+65
-14
lines changed

4 files changed

+65
-14
lines changed

doc/api/test.md

+5
Original file line numberDiff line numberDiff line change
@@ -2814,6 +2814,11 @@ are defined, while others are emitted in the order that the tests execute.
28142814
numbers and the number of times they were covered.
28152815
* `line` {number} The line number.
28162816
* `count` {number} The number of times the line was covered.
2817+
* `thresholds` {Object} An object containing whether or not the coverage for
2818+
each coverage type.
2819+
* `function` {boolean} Whether or not the coverage surpassed the `function` threshold.
2820+
* `branch` {boolean} Whether or not the coverage surpassed the `branch` threshold.
2821+
* `line` {boolean} Whether or not the coverage surpassed the `line` threshold.
28172822
* `totals` {Object} An object containing a summary of coverage for all
28182823
files.
28192824
* `totalLineCount` {number} The total number of lines.

lib/internal/test_runner/test.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -1010,8 +1010,12 @@ class Test extends AsyncResource {
10101010
reporter.diagnostic(nesting, loc, `duration_ms ${this.duration()}`);
10111011

10121012
if (coverage) {
1013-
reporter.coverage(nesting, loc, coverage);
1014-
1013+
coverage.thresholds = {
1014+
__proto__: null,
1015+
line: true,
1016+
branch: true,
1017+
function: true,
1018+
};
10151019
const coverages = [
10161020
{ __proto__: null, actual: coverage.totals.coveredLinePercent,
10171021
threshold: this.config.lineCoverage, name: 'line' },
@@ -1027,9 +1031,12 @@ class Test extends AsyncResource {
10271031
const { threshold, actual, name } = coverages[i];
10281032
if (actual < threshold) {
10291033
process.exitCode = kGenericUserError;
1034+
coverage.thresholds[name] = false;
10301035
reporter.diagnostic(nesting, loc, `Error: ${NumberPrototypeToFixed(actual, 2)}% ${name} coverage does not meet threshold of ${threshold}%.`);
10311036
}
10321037
}
1038+
1039+
reporter.coverage(nesting, loc, coverage);
10331040
}
10341041

10351042
if (harness.watching) {

test/parallel/test-runner-coverage-thresholds.js

+45-12
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,7 @@ function getTapCoverageFixtureReport() {
4444
}
4545

4646
const fixture = fixtures.path('test-runner', 'coverage.js');
47-
const neededArguments = [
48-
'--experimental-test-coverage',
49-
'--test-reporter', 'tap',
50-
];
47+
const reporter = fixtures.fileURL('test-runner/custom_reporters/coverage.mjs');
5148

5249
const coverages = [
5350
{ flag: '--test-coverage-lines', name: 'line', actual: 78.35 },
@@ -56,10 +53,12 @@ const coverages = [
5653
];
5754

5855
for (const coverage of coverages) {
59-
test(`test passing ${coverage.flag}`, async (t) => {
56+
test(`test passing ${coverage.flag}`, () => {
6057
const result = spawnSync(process.execPath, [
61-
...neededArguments,
58+
'--test',
59+
'--experimental-test-coverage',
6260
`${coverage.flag}=25`,
61+
'--test-reporter', 'tap',
6362
fixture,
6463
]);
6564

@@ -70,10 +69,27 @@ for (const coverage of coverages) {
7069
assert(!findCoverageFileForPid(result.pid));
7170
});
7271

73-
test(`test failing ${coverage.flag}`, async (t) => {
72+
test(`test passing ${coverage.flag} with custom reporter`, () => {
73+
const result = spawnSync(process.execPath, [
74+
'--test',
75+
'--experimental-test-coverage',
76+
`${coverage.flag}=25`,
77+
'--test-reporter', reporter,
78+
fixture,
79+
]);
80+
81+
const stdout = JSON.parse(result.stdout.toString());
82+
assert(stdout.summary.thresholds[coverage.name]);
83+
assert.strictEqual(result.status, 0);
84+
assert(!findCoverageFileForPid(result.pid));
85+
});
86+
87+
test(`test failing ${coverage.flag}`, () => {
7488
const result = spawnSync(process.execPath, [
75-
...neededArguments,
89+
'--test',
90+
'--experimental-test-coverage',
7691
`${coverage.flag}=99`,
92+
'--test-reporter', 'tap',
7793
fixture,
7894
]);
7995

@@ -84,9 +100,25 @@ for (const coverage of coverages) {
84100
assert(!findCoverageFileForPid(result.pid));
85101
});
86102

87-
test(`test out-of-range ${coverage.flag} (too high)`, async (t) => {
103+
test(`test failing ${coverage.flag} with custom reporter`, () => {
104+
const result = spawnSync(process.execPath, [
105+
'--test',
106+
'--experimental-test-coverage',
107+
`${coverage.flag}=99`,
108+
'--test-reporter', reporter,
109+
fixture,
110+
]);
111+
112+
const stdout = JSON.parse(result.stdout.toString());
113+
assert(!stdout.summary.thresholds[coverage.name]);
114+
assert.strictEqual(result.status, 1);
115+
assert(!findCoverageFileForPid(result.pid));
116+
});
117+
118+
test(`test out-of-range ${coverage.flag} (too high)`, () => {
88119
const result = spawnSync(process.execPath, [
89-
...neededArguments,
120+
'--test',
121+
'--experimental-test-coverage',
90122
`${coverage.flag}=101`,
91123
fixture,
92124
]);
@@ -96,9 +128,10 @@ for (const coverage of coverages) {
96128
assert(!findCoverageFileForPid(result.pid));
97129
});
98130

99-
test(`test out-of-range ${coverage.flag} (too low)`, async (t) => {
131+
test(`test out-of-range ${coverage.flag} (too low)`, () => {
100132
const result = spawnSync(process.execPath, [
101-
...neededArguments,
133+
'--test',
134+
'--experimental-test-coverage',
102135
`${coverage.flag}=-1`,
103136
fixture,
104137
]);

test/parallel/test-runner-coverage.js

+6
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ test('coverage reports on lines, functions, and branches', skipIfNoInspector, as
253253
const calledTwice = file.functions.find((f) => f.name === 'fnWithControlFlow');
254254
assert.strictEqual(calledTwice.count, 2);
255255
assert.strictEqual(calledTwice.line, 35);
256+
257+
assert.ok(coverage.summary.thresholds.function);
256258
});
257259

258260
await t.test('reports on branch coverage', () => {
@@ -261,6 +263,8 @@ test('coverage reports on lines, functions, and branches', skipIfNoInspector, as
261263

262264
const calledTwice = file.branches.find((b) => b.line === 35);
263265
assert.strictEqual(calledTwice.count, 2);
266+
267+
assert.ok(coverage.summary.thresholds.branch);
264268
});
265269

266270
await t.test('reports on line coverage', () => {
@@ -278,6 +282,8 @@ test('coverage reports on lines, functions, and branches', skipIfNoInspector, as
278282
const testLine = file.lines.find((l) => l.line === line.line);
279283
assert.strictEqual(testLine.count, line.count);
280284
});
285+
286+
assert.ok(coverage.summary.thresholds.line);
281287
});
282288
});
283289

0 commit comments

Comments
 (0)