Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion lib/internal/test_runner/coverage.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,6 +33,7 @@ const { fileURLToPath, URL } = require('internal/url');
const{ kMappings, SourceMap }=require('internal/source_map/source_map');
const{
codes: {
ERR_OPERATION_FAILED,
ERR_SOURCE_MAP_CORRUPT,
ERR_SOURCE_MAP_MISSING_SOURCE,
},
Expand DownExpand Up@@ -402,7 +403,7 @@ class TestCoverage {
}

constcoverageFile=join(this.coverageDirectory,entry.name);
constcoverage=JSONParse(readFileSync(coverageFile,'utf8'));
constcoverage=readCoverageFile(coverageFile);
this.mergeCoverage(result,this.mapCoverageWithSourceMap(coverage));
}

Expand DownExpand Up@@ -587,6 +588,24 @@ class TestCoverage {
}
}

functionreadCoverageFile(coverageFile){
constrawCoverage=readFileSync(coverageFile,'utf8');

if(rawCoverage.length===0){
thrownewERR_OPERATION_FAILED(`coverage file is empty: ${coverageFile}`);
}

try{
returnJSONParse(rawCoverage);
}catch(err){
consterror=newERR_OPERATION_FAILED(
`failed to parse coverage file ${coverageFile}: ${err.message}`,
);
error.cause=err;
throwerror;
}
}

functiontoPercentage(covered,total){
returntotal===0 ? 100 : (covered/total)*100;
}
Expand Down
45 changes: 31 additions & 14 deletions test/parallel/test-runner-coverage.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -77,6 +77,22 @@ function getSpecCoverageFixtureReport() {
return report;
}

function formatSpawnSyncResult(result) {
return [
`status: ${result.status}`,
`signal: ${result.signal}`,
`stdout:\n${result.stdout}`,
`stderr:\n${result.stderr}`,
].join('\n');
}

function assertIncludesReport(result, report) {
assert(
result.stdout.toString().includes(report),
formatSpawnSyncResult(result),
);
}

test('test coverage report', async (t) => {
await t.test('handles the inspector not being available', (t) => {
if (process.features.inspector) {
Expand DownExpand Up@@ -111,7 +127,7 @@ test('test tap coverage reporter', skipIfNoInspector, async (t) => {
const options = { env: { ...process.env, NODE_V8_COVERAGE: tmpdir.path } };
const result = spawnSync(process.execPath, args, options);
const report = getTapCoverageFixtureReport();
assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.stderr.toString(), '');
assert.strictEqual(result.status, 0);
assert(findCoverageFileForPid(result.pid));
Expand All@@ -129,7 +145,7 @@ test('test tap coverage reporter', skipIfNoInspector, async (t) => {
const result = spawnSync(process.execPath, args);
const report = getTapCoverageFixtureReport();

assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.stderr.toString(), '');
assert.strictEqual(result.status, 0);
assert(!findCoverageFileForPid(result.pid));
Expand All@@ -149,7 +165,7 @@ test('test spec coverage reporter', skipIfNoInspector, async (t) => {
const result = spawnSync(process.execPath, args, options);
const report = getSpecCoverageFixtureReport();

assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.stderr.toString(), '');
assert.strictEqual(result.status, 0);
assert(findCoverageFileForPid(result.pid));
Expand All@@ -166,7 +182,7 @@ test('test spec coverage reporter', skipIfNoInspector, async (t) => {
const result = spawnSync(process.execPath, args);
const report = getSpecCoverageFixtureReport();

assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.stderr.toString(), '');
assert.strictEqual(result.status, 0);
assert(!findCoverageFileForPid(result.pid));
Expand All@@ -187,7 +203,7 @@ test('single process coverage is the same with --test', skipIfNoInspector, () =>
const report = getTapCoverageFixtureReport();

assert.strictEqual(result.stderr.toString(), '');
assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.status, 0);
assert(!findCoverageFileForPid(result.pid));
});
Expand DownExpand Up@@ -226,7 +242,7 @@ test('coverage is combined for multiple processes', skipIfNoInspector, () => {
});

assert.strictEqual(result.stderr.toString(), '');
assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.status, 0);
});

Expand DownExpand Up@@ -268,7 +284,7 @@ test.skip('coverage works with isolation=none', skipIfNoInspector, common.mustCa
});

assert.strictEqual(result.stderr.toString(), '');
assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.status, 0);
}, 0));

Expand All@@ -285,6 +301,7 @@ test('coverage reports on lines, functions, and branches', skipIfNoInspector, as
]);
assert.strictEqual(child.stderr.toString(), '');
const stdout = child.stdout.toString();
assert.notStrictEqual(stdout, '', formatSpawnSyncResult(child));
const coverage = JSON.parse(stdout);

await t.test('does not include node_modules', () => {
Expand DownExpand Up@@ -366,7 +383,7 @@ test('coverage with ESM hook - source irrelevant', skipIfNoInspector, () => {
const result = spawnSync(process.execPath, args, { cwd: fixture });

assert.strictEqual(result.stderr.toString(), '');
assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.status, 0);
});

Expand DownExpand Up@@ -401,7 +418,7 @@ test('coverage with ESM hook - source transpiled', skipIfNoInspector, () => {
const result = spawnSync(process.execPath, args, { cwd: fixture });

assert.strictEqual(result.stderr.toString(), '');
assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.status, 0);
});

Expand DownExpand Up@@ -435,7 +452,7 @@ test('coverage with excluded files', skipIfNoInspector, () => {
return report.replaceAll('/', '\\');
}

assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.status, 0);
assert(!findCoverageFileForPid(result.pid));
});
Expand DownExpand Up@@ -472,7 +489,7 @@ test('coverage with included files', skipIfNoInspector, () => {
return report.replaceAll('/', '\\');
}

assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.status, 0);
assert(!findCoverageFileForPid(result.pid));
});
Expand DownExpand Up@@ -506,7 +523,7 @@ test('coverage with included and excluded files', skipIfNoInspector, () => {
return report.replaceAll('/', '\\');
}

assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.status, 0);
assert(!findCoverageFileForPid(result.pid));
});
Expand DownExpand Up@@ -547,7 +564,7 @@ test('correctly prints the coverage report of files contained in parent director
});

assert.strictEqual(result.stderr.toString(), '');
assert(result.stdout.toString().includes(report));
assertIncludesReport(result, report);
assert.strictEqual(result.status, 0);
});

Expand All@@ -564,5 +581,5 @@ test('coverage with directory and file named "file"', skipIfNoInspector, () => {

assert.strictEqual(result.stderr.toString(), '');
assert.strictEqual(result.status, 0);
assert(result.stdout.toString().includes('start of coverage report'));
assertIncludesReport(result, 'start of coverage report');
});
Loading