Skip to content

Commit 77cd1d5

Browse files
committed
test_runner: exclude ignored branches from LCOV coverage output
1 parent 1c9bd19 commit 77cd1d5

File tree

5 files changed

+56
-41
lines changed

5 files changed

+56
-41
lines changed

lib/internal/test_runner/coverage.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,9 @@ class TestCoverage {
199199
continue;
200200
}
201201

202-
// For uncovered branches, skip if all non-ignored lines are
203-
// already covered by other ranges. This handles the case where
204-
if (range.count === 0) {
202+
// For uncovered branches with some ignored lines, skip if all
203+
// non-ignored lines are already covered by other ranges. This
204+
if (range.count === 0 && range.ignoredLines > 0) {
205205
let hasUncoveredNonIgnoredLine = false;
206206
for (let l = 0; l < range.lines.length; ++l) {
207207
if (!range.lines[l].ignore && range.lines[l].count === 0) {

test/fixtures/test-runner/coverage-ignore-branch/source.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,15 @@ function getValue(condition) {
88
return 'falsy';
99
}
1010

11-
module.exports = { getValue };
11+
// This function has a branch where the ignored line is mixed with
12+
// non-ignored uncovered code, so the branch should still be reported.
13+
function getMixed(condition) {
14+
if (condition) {
15+
return 'yes';
16+
}
17+
/* node:coverage ignore next */
18+
const ignored = 'ignored';
19+
return ignored + ' no';
20+
}
21+
22+
module.exports = { getValue, getMixed };
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
'use strict';
22
const { test } = require('node:test');
33
const assert = require('node:assert');
4-
const { getValue } = require('./source.js');
4+
const { getValue, getMixed } = require('./source.js');
55

66
// Only call with true so the false branch is "uncovered" but ignored.
77
test('getValue returns truthy for true', () => {
88
assert.strictEqual(getValue(true), 'truthy');
99
});
10+
11+
// getMixed has a branch with both ignored and non-ignored uncovered lines.
12+
// The branch should still be reported as uncovered.
13+
test('getMixed returns yes for true', () => {
14+
assert.strictEqual(getMixed(true), 'yes');
15+
});

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,19 @@ function getTapCoverageFixtureReport() {
2323

2424
const report = [
2525
'# start of coverage report',
26-
'# --------------------------------------------------------------------------------------------',
26+
'# -----------------------------------------------------------------------------------------',
2727
'# file | line % | branch % | funcs % | uncovered lines',
28-
'# --------------------------------------------------------------------------------------------',
28+
'# -----------------------------------------------------------------------------------------',
2929
'# test | | | | ',
3030
'# fixtures | | | | ',
3131
'# test-runner | | | | ',
32-
'# coverage.js | 78.65 | 38.46 | 60.00 | 12-13 16-22 27 39 43-44 61-62 66-67 71-72',
32+
'# coverage.js | 79.78 | 38.46 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
3333
'# invalid-tap.js | 100.00 | 100.00 | 100.00 | ',
3434
'# v8-coverage | | | | ',
3535
'# throw.js | 71.43 | 50.00 | 100.00 | 5-6',
36-
'# --------------------------------------------------------------------------------------------',
37-
'# all files | 78.35 | 43.75 | 60.00 | ',
38-
'# --------------------------------------------------------------------------------------------',
36+
'# -----------------------------------------------------------------------------------------',
37+
'# all files | 79.38 | 43.75 | 60.00 | ',
38+
'# -----------------------------------------------------------------------------------------',
3939
'# end of coverage report',
4040
].join('\n');
4141

@@ -51,7 +51,7 @@ const fixture = fixtures.path('test-runner', 'coverage.js');
5151
const reporter = fixtures.fileURL('test-runner/custom_reporters/coverage.mjs');
5252

5353
const coverages = [
54-
{ flag: '--test-coverage-lines', name: 'line', actual: 78.35 },
54+
{ flag: '--test-coverage-lines', name: 'line', actual: 79.38 },
5555
{ flag: '--test-coverage-functions', name: 'function', actual: 60.00 },
5656
{ flag: '--test-coverage-branches', name: 'branch', actual: 43.75 },
5757
];

test/parallel/test-runner-coverage.js

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ function getTapCoverageFixtureReport() {
3131
'# test | | | | ',
3232
'# fixtures | | | | ',
3333
'# test-runner | | | | ',
34-
'# coverage.js | 79.78 | 41.67 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
34+
'# coverage.js | 79.78 | 38.46 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
3535
'# invalid-tap.js | 100.00 | 100.00 | 100.00 | ',
3636
'# v8-coverage | | | | ',
3737
'# throw.js | 71.43 | 50.00 | 100.00 | 5-6',
3838
'# -----------------------------------------------------------------------------------------',
39-
'# all files | 79.38 | 46.67 | 60.00 | ',
39+
'# all files | 79.38 | 43.75 | 60.00 | ',
4040
'# -----------------------------------------------------------------------------------------',
4141
'# end of coverage report',
4242
].join('\n');
@@ -59,12 +59,12 @@ function getSpecCoverageFixtureReport() {
5959
'\u2139 test | | | | ',
6060
'\u2139 fixtures | | | | ',
6161
'\u2139 test-runner | | | | ',
62-
'\u2139 coverage.js | 79.78 | 41.67 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
62+
'\u2139 coverage.js | 79.78 | 38.46 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
6363
'\u2139 invalid-tap.js | 100.00 | 100.00 | 100.00 | ',
6464
'\u2139 v8-coverage | | | | ',
6565
'\u2139 throw.js | 71.43 | 50.00 | 100.00 | 5-6',
6666
'\u2139 -----------------------------------------------------------------------------------------',
67-
'\u2139 all files | 79.38 | 46.67 | 60.00 | ',
67+
'\u2139 all files | 79.38 | 43.75 | 60.00 | ',
6868
'\u2139 -----------------------------------------------------------------------------------------',
6969
'\u2139 end of coverage report',
7070
].join('\n');
@@ -198,12 +198,12 @@ test('coverage is combined for multiple processes', skipIfNoInspector, () => {
198198
'# -------------------------------------------------------------------',
199199
'# file | line % | branch % | funcs % | uncovered lines',
200200
'# -------------------------------------------------------------------',
201-
'# common.js | 89.86 | 66.67 | 100.00 | 8 13-14 18 34-35 53',
201+
'# common.js | 89.86 | 62.50 | 100.00 | 8 13-14 18 34-35 53',
202202
'# first.test.js | 83.33 | 100.00 | 50.00 | 5-6',
203203
'# second.test.js | 100.00 | 100.00 | 100.00 | ',
204204
'# third.test.js | 100.00 | 100.00 | 100.00 | ',
205205
'# -------------------------------------------------------------------',
206-
'# all files | 92.11 | 76.19 | 88.89 | ',
206+
'# all files | 92.11 | 72.73 | 88.89 | ',
207207
'# -------------------------------------------------------------------',
208208
'# end of coverage report',
209209
].join('\n');
@@ -421,11 +421,11 @@ test('coverage with excluded files', skipIfNoInspector, () => {
421421
'# test | | | | ',
422422
'# fixtures | | | | ',
423423
'# test-runner | | | | ',
424-
'# coverage.js | 79.78 | 41.67 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
424+
'# coverage.js | 79.78 | 38.46 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
425425
'# v8-coverage | | | | ',
426426
'# throw.js | 71.43 | 50.00 | 100.00 | 5-6',
427427
'# --------------------------------------------------------------------------------------',
428-
'# all files | 79.17 | 42.86 | 60.00 | ',
428+
'# all files | 79.17 | 40.00 | 60.00 | ',
429429
'# --------------------------------------------------------------------------------------',
430430
'# end of coverage report',
431431
].join('\n');
@@ -458,11 +458,11 @@ test('coverage with included files', skipIfNoInspector, () => {
458458
'# test | | | | ',
459459
'# fixtures | | | | ',
460460
'# test-runner | | | | ',
461-
'# coverage.js | 79.78 | 41.67 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
461+
'# coverage.js | 79.78 | 38.46 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
462462
'# v8-coverage | | | | ',
463463
'# throw.js | 71.43 | 50.00 | 100.00 | 5-6',
464464
'# --------------------------------------------------------------------------------------',
465-
'# all files | 79.17 | 42.86 | 60.00 | ',
465+
'# all files | 79.17 | 40.00 | 60.00 | ',
466466
'# --------------------------------------------------------------------------------------',
467467
'# end of coverage report',
468468
].join('\n');
@@ -494,9 +494,9 @@ test('coverage with included and excluded files', skipIfNoInspector, () => {
494494
'# test | | | | ',
495495
'# fixtures | | | | ',
496496
'# test-runner | | | | ',
497-
'# coverage.js | 79.78 | 41.67 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
497+
'# coverage.js | 79.78 | 38.46 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
498498
'# --------------------------------------------------------------------------------------',
499-
'# all files | 79.78 | 41.67 | 60.00 | ',
499+
'# all files | 79.78 | 38.46 | 60.00 | ',
500500
'# --------------------------------------------------------------------------------------',
501501
'# end of coverage report',
502502
].join('\n');
@@ -518,13 +518,13 @@ test('correctly prints the coverage report of files contained in parent director
518518
'# file | line % | branch % | funcs % | uncovered lines',
519519
'# -----------------------------------------------------------------------------------------',
520520
'# .. | | | | ',
521-
'# coverage.js | 79.78 | 41.67 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
521+
'# coverage.js | 79.78 | 38.46 | 60.00 | 12 16-22 27 39 43-44 61-62 66-67 71-72',
522522
'# invalid-tap.js | 100.00 | 100.00 | 100.00 | ',
523523
'# .. | | | | ',
524524
'# v8-coverage | | | | ',
525525
'# throw.js | 71.43 | 50.00 | 100.00 | 5-6',
526526
'# -----------------------------------------------------------------------------------------',
527-
'# all files | 79.38 | 46.67 | 60.00 | ',
527+
'# all files | 79.38 | 43.75 | 60.00 | ',
528528
'# -----------------------------------------------------------------------------------------',
529529
'# end of coverage report',
530530
].join('\n');
@@ -573,29 +573,27 @@ test('coverage ignore comments exclude branches in lcov output', skipIfNoInspect
573573
.find((s) => s.includes('source.js'));
574574
assert(sourceSection, 'lcov output should contain source.js coverage');
575575

576-
// Verify that all branches are reported as covered (BRH should equal BRF).
577-
// The ignored branch should not penalize coverage.
578576
const brfMatch = sourceSection.match(/BRF:(\d+)/);
579577
const brhMatch = sourceSection.match(/BRH:(\d+)/);
580578
assert.match(sourceSection, /BRF:\d+/, 'lcov should contain BRF');
581579
assert.match(sourceSection, /BRH:\d+/, 'lcov should contain BRH');
580+
581+
// getValue's false branch is fully ignored, so it should be excluded.
582582
assert.strictEqual(
583-
brfMatch[1],
584-
brhMatch[1],
585-
`All branches should be covered when ignored code is excluded. ` +
583+
Number(brfMatch[1]),
584+
Number(brhMatch[1]) + 1,
585+
`Expected exactly one uncovered branch (getMixed). ` +
586586
`BRF=${brfMatch[1]}, BRH=${brhMatch[1]}`,
587587
);
588588

589-
// Verify no BRDA entries show 0 for the ignored branch.
590-
const brdaEntries = sourceSection.match(/BRDA:\d+,\d+,\d+,(\d+)/g) || [];
591-
for (const entry of brdaEntries) {
592-
const count = entry.match(/BRDA:\d+,\d+,\d+,(\d+)/)[1];
593-
assert.notStrictEqual(
594-
count,
595-
'0',
596-
`No branch should show 0 coverage when the path is ignored: ${entry}`,
597-
);
598-
}
589+
// Verify the only BRDA with count=0 is from getMixed (not getValue).
590+
const brdaEntries = sourceSection.match(/BRDA:\d+,\d+,\d+,\d+/g) || [];
591+
const uncoveredEntries = brdaEntries.filter((e) => e.endsWith(',0'));
592+
assert.strictEqual(
593+
uncoveredEntries.length,
594+
1,
595+
`Expected exactly one uncovered BRDA entry, got: ${uncoveredEntries}`,
596+
);
599597
});
600598

601599
// Regression test for https://github.com/nodejs/node/issues/61080

0 commit comments

Comments
 (0)