Skip to content

Commit ada1bd1

Browse files
committed
test_runner: report covered lines, functions and branches to reporters.
Fixes #49303
1 parent 0d080a2 commit ada1bd1

File tree

3 files changed

+52
-8
lines changed

3 files changed

+52
-8
lines changed

doc/api/test.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -2011,8 +2011,18 @@ object, streaming a series of events representing the execution of the tests.
20112011
* `coveredLinePercent` {number} The percentage of lines covered.
20122012
* `coveredBranchPercent` {number} The percentage of branches covered.
20132013
* `coveredFunctionPercent` {number} The percentage of functions covered.
2014-
* `uncoveredLineNumbers` {Array} An array of integers representing line
2015-
numbers that are uncovered.
2014+
* `functions` {Array} An array of functions representing function
2015+
coverage.
2016+
* `name` {string} The name of the function.
2017+
* `line` {number} The line number where the function is defined.
2018+
* `count` {number} The number of times the function was called.
2019+
* `branches` {Array} An array of branches representing branch coverage.
2020+
* `line` {number} The line number where the branch is defined.
2021+
* `count` {number} The number of times the branch was taken.
2022+
* `lines` {Array} An array of lines representing line
2023+
numbers and the number of times they were covered.
2024+
* `line` {number} The line number.
2025+
* `count` {number} The number of times the line was covered.
20162026
* `totals` {Object} An object containing a summary of coverage for all
20172027
files.
20182028
* `totalLineCount` {number} The total number of lines.

lib/internal/test_runner/coverage.js

+27-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const {
1313
StringPrototypeIncludes,
1414
StringPrototypeLocaleCompare,
1515
StringPrototypeStartsWith,
16+
MathMax
1617
} = primordials;
1718
const {
1819
copyFileSync,
@@ -43,6 +44,7 @@ class CoverageLine {
4344
this.startOffset = startOffset;
4445
this.endOffset = startOffset + src.length - newlineLength;
4546
this.ignore = false;
47+
this.count = 0;
4648
this.#covered = true;
4749
}
4850

@@ -118,6 +120,8 @@ class TestCoverage {
118120
let totalFunctions = 0;
119121
let branchesCovered = 0;
120122
let functionsCovered = 0;
123+
const functionReports = [];
124+
const branchReports = [];
121125

122126
const lines = ArrayPrototypeMap(linesWithBreaks, (line, i) => {
123127
const startOffset = offset;
@@ -165,6 +169,11 @@ class TestCoverage {
165169
mapRangeToLines(range, lines);
166170

167171
if (isBlockCoverage) {
172+
ArrayPrototypePush(branchReports, {
173+
line: range.lines[0].line,
174+
count: range.count
175+
});
176+
168177
if (range.count !== 0 ||
169178
range.ignoredLines === range.lines.length) {
170179
branchesCovered++;
@@ -177,6 +186,12 @@ class TestCoverage {
177186
if (j > 0 && ranges.length > 0) {
178187
const range = ranges[0];
179188

189+
ArrayPrototypePush(functionReports, {
190+
name: functions[j].functionName,
191+
count: MathMax(...ArrayPrototypeMap(ranges, r => r.count)),
192+
line: range.lines[0].line
193+
});
194+
180195
if (range.count !== 0 || range.ignoredLines === range.lines.length) {
181196
functionsCovered++;
182197
}
@@ -186,15 +201,18 @@ class TestCoverage {
186201
}
187202

188203
let coveredCnt = 0;
189-
const uncoveredLineNums = [];
204+
const lineReports = [];
190205

191206
for (let j = 0; j < lines.length; ++j) {
192207
const line = lines[j];
193208

194209
if (line.covered || line.ignore) {
195210
coveredCnt++;
211+
if (!line.ignore) {
212+
ArrayPrototypePush(lineReports, { line: line.line, count: line.count })
213+
}
196214
} else {
197-
ArrayPrototypePush(uncoveredLineNums, line.line);
215+
ArrayPrototypePush(lineReports, { line: line.line, count: 0 });
198216
}
199217
}
200218

@@ -210,7 +228,9 @@ class TestCoverage {
210228
coveredLinePercent: toPercentage(coveredCnt, lines.length),
211229
coveredBranchPercent: toPercentage(branchesCovered, totalBranches),
212230
coveredFunctionPercent: toPercentage(functionsCovered, totalFunctions),
213-
uncoveredLineNumbers: uncoveredLineNums,
231+
functions: functionReports,
232+
branches: branchReports,
233+
lines: lineReports,
214234
});
215235

216236
coverageSummary.totals.totalLineCount += lines.length;
@@ -321,6 +341,10 @@ function mapRangeToLines(range, lines) {
321341
endOffset >= line.endOffset) {
322342
line.covered = false;
323343
}
344+
if (count > 0 && startOffset <= line.startOffset &&
345+
endOffset >= line.endOffset) {
346+
line.count = count;
347+
}
324348

325349
ArrayPrototypePush(mappedLines, line);
326350

lib/internal/test_runner/utils.js

+13-3
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,15 @@ function formatLinesToRanges(values) {
297297
}, []), (range) => ArrayPrototypeJoin(range, '-'));
298298
}
299299

300+
function getUncoveredLines(lines) {
301+
return ArrayPrototypeReduce(lines, (acc, line) => {
302+
if (line.count === 0) {
303+
ArrayPrototypePush(acc, line.line);
304+
}
305+
return acc;
306+
}, []);
307+
}
308+
300309
function formatUncoveredLines(lines, table) {
301310
if (table) return ArrayPrototypeJoin(formatLinesToRanges(lines), ' ');
302311
return ArrayPrototypeJoin(lines, ', ');
@@ -325,8 +334,9 @@ function getCoverageReport(pad, summary, symbol, color, table) {
325334
columnPadLengths = ArrayPrototypeMap(kColumns, (column) => (table ? MathMax(column.length, 6) : 0));
326335
const columnsWidth = ArrayPrototypeReduce(columnPadLengths, (acc, columnPadLength) => acc + columnPadLength + 3, 0);
327336

328-
uncoveredLinesPadLength = table && ArrayPrototypeReduce(summary.files, (acc, file) =>
329-
MathMax(acc, formatUncoveredLines(file.uncoveredLineNumbers, table).length), 0);
337+
uncoveredLinesPadLength = table && ArrayPrototypeReduce(summary.files, (acc, file) => {
338+
return MathMax(acc, formatUncoveredLines(getUncoveredLines(file.lines), table).length)
339+
}, 0);
330340
uncoveredLinesPadLength = MathMax(uncoveredLinesPadLength, 'uncovered lines'.length);
331341
const uncoveredLinesWidth = uncoveredLinesPadLength + 2;
332342

@@ -388,7 +398,7 @@ function getCoverageReport(pad, summary, symbol, color, table) {
388398

389399
report += `${prefix}${getCell(relativePath, filePadLength, StringPrototypePadEnd, truncateStart, fileCoverage)}${kSeparator}` +
390400
`${ArrayPrototypeJoin(ArrayPrototypeMap(coverages, (coverage, j) => getCell(NumberPrototypeToFixed(coverage, 2), columnPadLengths[j], StringPrototypePadStart, false, coverage)), kSeparator)}${kSeparator}` +
391-
`${getCell(formatUncoveredLines(file.uncoveredLineNumbers, table), uncoveredLinesPadLength, false, truncateEnd)}\n`;
401+
`${getCell(formatUncoveredLines(getUncoveredLines(file.lines), table), uncoveredLinesPadLength, false, truncateEnd)}\n`;
392402
}
393403

394404
// Foot

0 commit comments

Comments
 (0)