Skip to content

test_runner: exclude ignored lines from BRDA in lcov output#61598

Open
RajeshKumar11 wants to merge 1 commit intonodejs:mainfrom
RajeshKumar11:fix/coverage-ignore-branch-lcov-61586
Open

test_runner: exclude ignored lines from BRDA in lcov output#61598
RajeshKumar11 wants to merge 1 commit intonodejs:mainfrom
RajeshKumar11:fix/coverage-ignore-branch-lcov-61586

Conversation

@RajeshKumar11
Copy link

Summary

When using /* node:coverage ignore next */ comments, the coverage system correctly excluded lines from DA (line coverage) entries in LCOV output but still reported branches as uncovered (BRDA count=0).

This caused branch coverage to show incorrect percentages (e.g., 66% instead of 100%) when the uncovered branch path contained ignored lines, impacting CI/CD pipelines that enforce branch coverage thresholds.

Changes

The fix treats branches as covered when they have count === 0 but contain ignored lines (ignoredLines > 0). This matches the behavior of c8 and ensures ignored code doesn't penalize branch coverage.

Before:

BRDA:4,2,0,0  # uncovered branch at line 4
BRH:2         # only 2/3 branches hit (66%)

After:

BRDA:4,2,0,1  # branch treated as covered due to ignore comment
BRH:3         # all 3/3 branches hit (100%)

Test plan

  • Added regression test in test/parallel/test-runner-coverage.js
  • Test verifies that BRDA entries don't show 0 for ignored branches
  • Test verifies BRH equals BRF when ignored code is not executed

Fixes: #61586

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/test_runner

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem. labels Jan 31, 2026
Copy link
Member

@JakobJingleheimer JakobJingleheimer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this!

I'm not familiar with LCOV itself, but the logic looks right.

Comment on lines 596 to 598
assert.strictEqual(brfMatch[1], brhMatch[1],
`All branches should be covered when ignored code is not executed. ` +
`BRF=${brfMatch[1]}, BRH=${brhMatch[1]}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: no mangling please :)

Suggested change
assert.strictEqual(brfMatch[1], brhMatch[1],
`All branches should be covered when ignored code is not executed. ` +
`BRF=${brfMatch[1]}, BRH=${brhMatch[1]}`);
assert.strictEqual(
brfMatch[1],
brhMatch[1],
`All branches should be covered when ignored code is not executed. BRF=${brfMatch[1]}, BRH=${brhMatch[1]}`,
);

Comment on lines 605 to 607
assert.notStrictEqual(count, '0',
`No branch should show 0 coverage when the ` +
`uncovered path is ignored: ${entry}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: no mangling please :)

Suggested change
assert.notStrictEqual(count, '0',
`No branch should show 0 coverage when the ` +
`uncovered path is ignored: ${entry}`);
assert.notStrictEqual(
count,
'0',
`No branch should show 0 coverage when the uncovered path is ignored: ${entry}`,
);

Comment on lines 592 to 595
const brfMatch = sourceSection.match(/BRF:(\d+)/);
const brhMatch = sourceSection.match(/BRH:(\d+)/);
assert(brfMatch, 'LCOV should contain BRF');
assert(brhMatch, 'LCOV should contain BRH');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const brfMatch = sourceSection.match(/BRF:(\d+)/);
const brhMatch = sourceSection.match(/BRH:(\d+)/);
assert(brfMatch, 'LCOV should contain BRF');
assert(brhMatch, 'LCOV should contain BRH');
assert.match(sourceSection, /BRF:(\d+)/, 'LCOV should contain BRF');
assert.match(sourceSection, /BRH:(\d+)/, 'LCOV should contain BRH');

Comment on lines 586 to 587
const sourceSection = lcov.split('end_of_record')
.find((s) => s.includes('source.js'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
const sourceSection = lcov.split('end_of_record')
.find((s) => s.includes('source.js'));
const sourceSection = lcov
.split('end_of_record')
.find((s) => s.includes('source.js'));

or

Suggested change
const sourceSection = lcov.split('end_of_record')
.find((s) => s.includes('source.js'));
const sourceSection = lcov.split('end_of_record').find((s) => s.includes('source.js'));

Comment on lines 204 to 205
const branchCount = (range.count === 0 && range.ignoredLines > 0) ?
1 : range.count;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const branchCount = (range.count === 0 && range.ignoredLines > 0) ?
1 : range.count;
const branchCount = (range.count === 0 && range.ignoredLines > 0) ? 1 : range.count;

@RajeshKumar11
Copy link
Author

Applied the formatting suggestions, thanks for the review!

Copy link
Member

@JakobJingleheimer JakobJingleheimer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I'd like to get someone more familiar with LCOV syntax to review/approve before landing.

When using `/* node:coverage ignore next */` comments, the coverage
system correctly excluded lines from DA (line coverage) entries in
LCOV output but still reported branches as uncovered (BRDA count=0).

This caused branch coverage to show incorrect percentages (e.g., 66%
instead of 100%) when the uncovered branch path contained ignored
lines, impacting CI/CD pipelines that enforce branch coverage thresholds.

The fix treats branches as covered when they have `count === 0` but
contain ignored lines (`ignoredLines > 0`). This matches the behavior
of c8 and ensures ignored code doesn't penalize branch coverage.

Fixes: nodejs#61586
@RajeshKumar11 RajeshKumar11 force-pushed the fix/coverage-ignore-branch-lcov-61586 branch from aa9d3db to 5caffef Compare February 5, 2026 14:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem.

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

test_runner: node:coverage ignore comments exclude DA but leave BRDA in lcov output

3 participants