Skip to content

Commit

Permalink
test_runner: exclude test files from coverage by default
Browse files Browse the repository at this point in the history
  • Loading branch information
pmarchini committed Nov 28, 2024
1 parent b17a1fb commit fb8f062
Show file tree
Hide file tree
Showing 21 changed files with 302 additions and 185 deletions.
5 changes: 5 additions & 0 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -2290,6 +2290,7 @@ This option may be specified multiple times to exclude multiple glob patterns.

If both `--test-coverage-exclude` and `--test-coverage-include` are provided,
files must meet **both** criteria to be included in the coverage report.
However, if there is an overlap between the two, `--test-coverage-include` takes precedence.

### `--test-coverage-functions=threshold`

Expand Down Expand Up @@ -2318,6 +2319,10 @@ This option may be specified multiple times to include multiple glob patterns.

If both `--test-coverage-exclude` and `--test-coverage-include` are provided,
files must meet **both** criteria to be included in the coverage report.
However, if there is an overlap between the two, `--test-coverage-include` takes precedence.

By default, the test files are excluded from code coverage. They can be explicitly
included via this flag.

### `--test-coverage-lines=threshold`

Expand Down
8 changes: 6 additions & 2 deletions doc/api/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -1341,14 +1341,18 @@ changes:
* `coverageExcludeGlobs` {string|Array} Excludes specific files from code coverage
using a glob pattern, which can match both absolute and relative file paths.
This property is only applicable when `coverage` was set to `true`.
If both `coverageExcludeGlobs` and `coverageIncludeGlobs` are provided,
If both `--test-coverage-exclude` and `--test-coverage-include` are provided,
files must meet **both** criteria to be included in the coverage report.
However, if there is an overlap between the two, `--test-coverage-include` takes precedence.
**Default:** `undefined`.
* `coverageIncludeGlobs` {string|Array} Includes specific files in code coverage
using a glob pattern, which can match both absolute and relative file paths.
This property is only applicable when `coverage` was set to `true`.
If both `coverageExcludeGlobs` and `coverageIncludeGlobs` are provided,
If both `--test-coverage-exclude` and `--test-coverage-include` are provided,
files must meet **both** criteria to be included in the coverage report.
However, if there is an overlap between the two, `--test-coverage-include` takes precedence.
By default, the test files are excluded from code coverage. They can be explicitly
included via this flag.
**Default:** `undefined`.
* `lineCoverage` {number} Require a minimum percent of covered lines. If code
coverage does not reach the threshold specified, the process will exit with code `1`.
Expand Down
42 changes: 31 additions & 11 deletions lib/internal/test_runner/coverage.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ const {
readFileSync,
rmSync,
} = require('fs');
const { setupCoverageHooks } = require('internal/util');
const { setupCoverageHooks, isWindows, isMacOS } = require('internal/util');
const { tmpdir } = require('os');
const { join, resolve, relative, matchesGlob } = require('path');
const { join, resolve, relative } = require('path');
const { fileURLToPath } = require('internal/url');
const { kMappings, SourceMap } = require('internal/source_map/source_map');
const {
Expand All @@ -42,6 +42,25 @@ const kLineEndingRegex = /\r?\n$/u;
const kLineSplitRegex = /(?<=\r?\n)/u;
const kStatusRegex = /\/\* node:coverage (?<status>enable|disable) \*\//;

let minimatch;
function lazyMinimatch() {
minimatch ??= require('internal/deps/minimatch/index');
return minimatch;
}

function glob(path, pattern, windows) {
return lazyMinimatch().minimatch(path, pattern, {
__proto__: null,
nocase: isMacOS || isWindows,
windowsPathsNoEscape: true,
nonegate: true,
nocomment: true,
optimizationLevel: 2,
platform: windows ? 'win32' : 'posix',
nocaseMagicOnly: true,
});
}

class CoverageLine {
constructor(line, startOffset, src, length = src?.length) {
const newlineLength = src == null ? 0 :
Expand Down Expand Up @@ -464,23 +483,24 @@ class TestCoverage {
coverageExcludeGlobs: excludeGlobs,
coverageIncludeGlobs: includeGlobs,
} = this.options;
// This check filters out files that match the exclude globs.
if (excludeGlobs?.length > 0) {
for (let i = 0; i < excludeGlobs.length; ++i) {
if (matchesGlob(relativePath, excludeGlobs[i]) ||
matchesGlob(absolutePath, excludeGlobs[i])) return true;
}
}

// This check filters out files that do not match the include globs.
if (includeGlobs?.length > 0) {
for (let i = 0; i < includeGlobs.length; ++i) {
if (matchesGlob(relativePath, includeGlobs[i]) ||
matchesGlob(absolutePath, includeGlobs[i])) return false;
if (glob(relativePath, includeGlobs[i]) ||
glob(absolutePath, includeGlobs[i])) return false;
}
return true;
}

// This check filters out files that match the exclude globs.
if (excludeGlobs?.length > 0) {
for (let i = 0; i < excludeGlobs.length; ++i) {
if (glob(relativePath, excludeGlobs[i]) ||
glob(absolutePath, excludeGlobs[i])) return true;
}
}

// This check filters out the node_modules/ directory, unless it is explicitly included.
return StringPrototypeIncludes(url, '/node_modules/');
}
Expand Down
8 changes: 8 additions & 0 deletions lib/internal/test_runner/harness.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,13 @@ function setupProcessState(root, globalOptions) {
root.harness.teardown = exitHandler;
}

function excludeTestFileFromCoverage(testFile, globalOptions) {
if (globalOptions.coverageExcludeGlobs === undefined) {
globalOptions.coverageExcludeGlobs = [];
}
ArrayPrototypePush(globalOptions.coverageExcludeGlobs, testFile);
}

function lazyBootstrapRoot() {
if (!globalRoot) {
// This is where the test runner is bootstrapped when node:test is used
Expand All @@ -261,6 +268,7 @@ function lazyBootstrapRoot() {
};
const globalOptions = parseCommandLine();
globalOptions.cwd = process.cwd();
excludeTestFileFromCoverage(entryFile, globalOptions);
createTestTree(rootTestOptions, globalOptions);
globalRoot.reporter.on('test:summary', (data) => {
if (!data.success) {
Expand Down
7 changes: 6 additions & 1 deletion lib/internal/test_runner/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,12 @@ function run(options = kEmptyObject) {
validateStringArray(argv, 'options.argv');
validateStringArray(execArgv, 'options.execArgv');

let testFiles = files ?? createTestFileList(globPatterns, cwd);
if (coverageExcludeGlobs === undefined) {
coverageExcludeGlobs = [];
}
ArrayPrototypePush(coverageExcludeGlobs, ...testFiles);

const rootTestOptions = { __proto__: null, concurrency, timeout, signal };
const globalOptions = {
__proto__: null,
Expand All @@ -680,7 +686,6 @@ function run(options = kEmptyObject) {
cwd,
};
const root = createTestTree(rootTestOptions, globalOptions);
let testFiles = files ?? createTestFileList(globPatterns, cwd);

if (shard) {
testFiles = ArrayPrototypeFilter(testFiles, (_, index) => index % shard.total === shard.index - 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,16 @@ ok 1 - Coverage Print Fixed Width 100
# duration_ms *
# start of coverage report
# --------------------------------------------------------------------------------------------------
# file | line % | branch % | funcs % | uncovered lines
# file | line % | branch % | funcs % | uncovered lines
# --------------------------------------------------------------------------------------------------
# test | | | |
# fixtures | | | |
# test-runner | | | |
# coverage-snap | | | |
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 …
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# many-uncovered-lines.js | 50.99 | 42.86 | 1.92 | 5-7 9-11 13-15 17-19 …
# output | | | |
# coverage-width-100-uncovered-lines.mjs | 100.00 | 100.00 | 100.00 |
# test | | | |
# fixtures | | | |
# test-runner | | | |
# coverage-snap | | | |
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-…
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# many-uncovered-lines.js | 50.99 | 42.86 | 1.92 | 5-7 9-11 13-15 17-19 29-30 40-42 45-…
# --------------------------------------------------------------------------------------------------
# all files | 52.80 | 60.00 | 1.61 |
# all files | 51.44 | 55.56 | 1.61 |
# --------------------------------------------------------------------------------------------------
# end of coverage report
26 changes: 12 additions & 14 deletions test/fixtures/test-runner/output/coverage-width-100.snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,16 @@ ok 1 - Coverage Print Fixed Width 100
# todo 0
# duration_ms *
# start of coverage report
# --------------------------------------------------------------------------------------------------
# file | line % | branch % | funcs % | uncovered lines
# --------------------------------------------------------------------------------------------------
# test | | | |
# fixtures | | | |
# test-runner | | | |
# coverage-snap | | | |
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-4…
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# output | | | |
# coverage-width-100.mjs | 100.00 | 100.00 | 100.00 |
# --------------------------------------------------------------------------------------------------
# all files | 60.81 | 100.00 | 0.00 |
# --------------------------------------------------------------------------------------------------
# -----------------------------------------------------------------------------------------------
# file | line % | branch % | funcs % | uncovered lines
# -----------------------------------------------------------------------------------------------
# test | | | |
# fixtures | | | |
# test-runner | | | |
# coverage-snap | | | |
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# -----------------------------------------------------------------------------------------------
# all files | 53.97 | 100.00 | 0.00 |
# -----------------------------------------------------------------------------------------------
# end of coverage report
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,16 @@ ok 1 - Coverage Print Fixed Width 150
# duration_ms *
# start of coverage report
# ----------------------------------------------------------------------------------------------------------------------------------------------------
# file | line % | branch % | funcs % | uncovered lines
# file | line % | branch % | funcs % | uncovered lines
# ----------------------------------------------------------------------------------------------------------------------------------------------------
# test | | | |
# fixtures | | | |
# test-runner | | | |
# coverage-snap | | | |
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# many-uncovered-lines.js | 50.99 | 42.86 | 1.92 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52 55-57 59-61 63-65 67-69 91…
# output | | | |
# coverage-width-150-uncovered-lines.mjs | 100.00 | 100.00 | 100.00 |
# test | | | |
# fixtures | | | |
# test-runner | | | |
# coverage-snap | | | |
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# many-uncovered-lines.js | 50.99 | 42.86 | 1.92 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52 55-57 59-61 63-65 67-69 91-93 96-98 100-1…
# ----------------------------------------------------------------------------------------------------------------------------------------------------
# all files | 52.80 | 60.00 | 1.61 |
# all files | 51.44 | 55.56 | 1.61 |
# ----------------------------------------------------------------------------------------------------------------------------------------------------
# end of coverage report
26 changes: 12 additions & 14 deletions test/fixtures/test-runner/output/coverage-width-150.snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,16 @@ ok 1 - Coverage Print Fixed Width 150
# todo 0
# duration_ms *
# start of coverage report
# --------------------------------------------------------------------------------------------------------
# file | line % | branch % | funcs % | uncovered lines
# --------------------------------------------------------------------------------------------------------
# test | | | |
# fixtures | | | |
# test-runner | | | |
# coverage-snap | | | |
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# output | | | |
# coverage-width-150.mjs | 100.00 | 100.00 | 100.00 |
# --------------------------------------------------------------------------------------------------------
# all files | 60.81 | 100.00 | 0.00 |
# --------------------------------------------------------------------------------------------------------
# -----------------------------------------------------------------------------------------------
# file | line % | branch % | funcs % | uncovered lines
# -----------------------------------------------------------------------------------------------
# test | | | |
# fixtures | | | |
# test-runner | | | |
# coverage-snap | | | |
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# -----------------------------------------------------------------------------------------------
# all files | 53.97 | 100.00 | 0.00 |
# -----------------------------------------------------------------------------------------------
# end of coverage report
4 changes: 1 addition & 3 deletions test/fixtures/test-runner/output/coverage-width-40.snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ ok 1 - Coverage Print Fixed Width 40
# c.js | 55.77 | 100.00 | 0.00 | …
# a.js | 55.77 | 100.00 | 0.00 | …
# b.js | 45.45 | 100.00 | 0.00 | …
# output | | | |
# …e-width-40.mjs | 100.00 | 100.00 | 100.00 |
# --------------------------------------
# all files | 59.06 | 100.00 | 0.00 |
# all files | 54.78 | 100.00 | 0.00 |
# --------------------------------------
# end of coverage report
18 changes: 8 additions & 10 deletions test/fixtures/test-runner/output/coverage-width-80-color.snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,16 @@
[34mℹ duration_ms *[39m
[34mℹ start of coverage report
ℹ ------------------------------------------------------------------------------
ℹ file | [31mline %[34m | [31mbranch %[34m | [31mfuncs %[34m | uncovered
ℹ file | [31mline %[34m | [31mbranch %[34m | [31mfuncs %[34m | uncovered lines
ℹ ------------------------------------------------------------------------------
ℹ test | [31m [34m | [31m [34m | [31m [34m |
ℹ fixtures | [31m [34m | [31m [34m | [31m [34m |
ℹ test-runner | [31m [34m | [31m [34m | [31m [34m |
ℹ coverage-snap | [31m [34m | [31m [34m | [31m [34m |
ℹ [33ma.js [34m | [33m 55.77[34m | [32m 100.00[34m | [31m 0.00[34m | 5-7 9-11 1…
ℹ [31mb.js [34m | [31m 45.45[34m | [32m 100.00[34m | [31m 0.00[34m | 5-7 9-11
ℹ output | [31m [34m | [31m [34m | [31m [34m |
ℹ [32mcoverage-width-80-color.mjs [34m | [32m100.00[34m | [32m 100.00[34m | [32m 100.00[34m |
ℹ test | [31m [34m | [31m [34m | [31m [34m |
ℹ fixtures | [31m [34m | [31m [34m | [31m [34m |
ℹ test-runner | [31m [34m | [31m [34m | [31m [34m |
ℹ coverage-snap | [31m [34m | [31m [34m | [31m [34m |
ℹ [33ma.js [34m | [33m 55.77[34m | [32m 100.00[34m | [31m 0.00[34m | 5-7 9-11 13-15 17-19 29-…
ℹ [31mb.js [34m | [31m 45.45[34m | [32m 100.00[34m | [31m 0.00[34m | 5-7 9-11
ℹ ------------------------------------------------------------------------------
ℹ all files | [33m 61.33[34m | [32m 100.00[34m | [31m 0.00[34m |
ℹ all files | [33m 53.97[34m | [32m 100.00[34m | [31m 0.00[34m |
ℹ ------------------------------------------------------------------------------
ℹ end of coverage report
[39m
Loading

0 comments on commit fb8f062

Please sign in to comment.