Skip to content

Commit ac0a452

Browse files
committed
test_runner: omit ignored uncovered branches in lcov
Ignored `node:coverage` regions should not generate uncovered BRDA entries in lcov output. Align branch summaries with emitted BRDA lines and add a regression test fixture. Made-with: Cursor
1 parent 69fdff9 commit ac0a452

4 files changed

Lines changed: 51 additions & 3 deletions

File tree

lib/internal/test_runner/coverage.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ class TestCoverage {
197197
__proto__: null,
198198
line: range.lines[0]?.line,
199199
count: range.count,
200+
ignored: range.ignoredLines !== 0,
200201
});
201202

202203
if (range.count !== 0 ||

lib/internal/test_runner/reporter/lcov.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,26 @@ class LcovReporter extends Transform {
6868
// Taken is either '-' if the basic block containing the branch was
6969
// never executed or a number indicating how often that branch was
7070
// taken.
71+
let lcovBranchCount = 0;
72+
let lcovCoveredBranchCount = 0;
7173
for (let j = 0; j < file.branches.length; j++) {
72-
lcov += `BRDA:${file.branches[j].line},${j},0,${file.branches[j].count}\n`;
74+
const branch = file.branches[j];
75+
// Ignored lines should not produce uncovered BRDA entries.
76+
if (branch.ignored && branch.count === 0) {
77+
continue;
78+
}
79+
lcov += `BRDA:${branch.line},${j},0,${branch.count}\n`;
80+
lcovBranchCount++;
81+
if (branch.count > 0) {
82+
lcovCoveredBranchCount++;
83+
}
7384
}
7485

7586
// Branch coverage summaries are stored in two lines:
7687
// ## BRF:\<number of branches found\>
7788
// ## BRH:\<number of branches hit\>
78-
lcov += `BRF:${file.totalBranchCount}\n`;
79-
lcov += `BRH:${file.coveredBranchCount}\n`;
89+
lcov += `BRF:${lcovBranchCount}\n`;
90+
lcov += `BRH:${lcovCoveredBranchCount}\n`;
8091

8192
// Then there is a list of execution counts for each instrumented line
8293
// (i.e. a line which resulted in executable code):
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use strict';
2+
3+
const test = require('node:test');
4+
const assert = require('node:assert');
5+
6+
function getValue(condition) {
7+
if (condition) {
8+
return 'truthy';
9+
}
10+
/* node:coverage ignore next */
11+
return 'falsy';
12+
}
13+
14+
test('returns truthy', () => {
15+
assert.strictEqual(getValue(true), 'truthy');
16+
});

test/parallel/test-runner-coverage.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,26 @@ test('coverage with included and excluded files', skipIfNoInspector, () => {
511511
assert(!findCoverageFileForPid(result.pid));
512512
});
513513

514+
test('lcov omits uncovered ignored branches', skipIfNoInspector, () => {
515+
const fixture = fixtures.path('test-runner', 'coverage-ignore-next-branch.js');
516+
const args = [
517+
'--test',
518+
'--experimental-test-coverage',
519+
'--test-reporter',
520+
'lcov',
521+
fixture,
522+
];
523+
const result = spawnSync(process.execPath, args);
524+
const stdout = result.stdout.toString();
525+
526+
assert.strictEqual(result.stderr.toString(), '');
527+
assert.strictEqual(result.status, 0);
528+
assert.match(stdout, /SF:test\/fixtures\/test-runner\/coverage-ignore-next-branch\.js/);
529+
assert.match(stdout, /BRF:\d+/);
530+
assert.match(stdout, /BRH:\d+/);
531+
assert.doesNotMatch(stdout, /^BRDA:.*,0$/m);
532+
});
533+
514534
test('correctly prints the coverage report of files contained in parent directories', skipIfNoInspector, () => {
515535
let report = [
516536
'# start of coverage report',

0 commit comments

Comments
 (0)