Skip to content

Commit ea9a675

Browse files
pmarchiniaduh95
authored andcommitted
test_runner: exclude test files from coverage by default
PR-URL: #56060 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
1 parent 78743b1 commit ea9a675

18 files changed

+328
-55
lines changed

doc/api/cli.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2267,6 +2267,9 @@ This option may be specified multiple times to exclude multiple glob patterns.
22672267
If both `--test-coverage-exclude` and `--test-coverage-include` are provided,
22682268
files must meet **both** criteria to be included in the coverage report.
22692269

2270+
By default all the matching test files are excluded from the coverage report.
2271+
Specifying this option will override the default behavior.
2272+
22702273
### `--test-coverage-functions=threshold`
22712274

22722275
<!-- YAML

doc/api/test.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,10 @@ all tests have completed. If the [`NODE_V8_COVERAGE`][] environment variable is
476476
used to specify a code coverage directory, the generated V8 coverage files are
477477
written to that directory. Node.js core modules and files within
478478
`node_modules/` directories are, by default, not included in the coverage report.
479-
However, they can be explicitly included via the [`--test-coverage-include`][] flag. If
480-
coverage is enabled, the coverage report is sent to any [test reporters][] via
479+
However, they can be explicitly included via the [`--test-coverage-include`][] flag.
480+
By default all the matching test files are excluded from the coverage report.
481+
Exclusions can be overridden by using the [`--test-coverage-exclude`][] flag.
482+
If coverage is enabled, the coverage report is sent to any [test reporters][] via
481483
the `'test:coverage'` event.
482484

483485
Coverage can be disabled on a series of lines using the following
@@ -3592,6 +3594,7 @@ Can be used to abort test subtasks when the test has been aborted.
35923594
[`--experimental-test-module-mocks`]: cli.md#--experimental-test-module-mocks
35933595
[`--import`]: cli.md#--importmodule
35943596
[`--test-concurrency`]: cli.md#--test-concurrency
3597+
[`--test-coverage-exclude`]: cli.md#--test-coverage-exclude
35953598
[`--test-coverage-include`]: cli.md#--test-coverage-include
35963599
[`--test-name-pattern`]: cli.md#--test-name-pattern
35973600
[`--test-only`]: cli.md#--test-only

lib/internal/fs/glob.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,30 @@ class Glob {
650650
}
651651
}
652652

653+
/**
654+
* Check if a path matches a glob pattern
655+
* @param {string} path the path to check
656+
* @param {string} pattern the glob pattern to match
657+
* @param {boolean} windows whether the path is on a Windows system, defaults to `isWindows`
658+
* @returns {boolean}
659+
*/
660+
function matchGlobPattern(path, pattern, windows = isWindows) {
661+
validateString(path, 'path');
662+
validateString(pattern, 'pattern');
663+
return lazyMinimatch().minimatch(path, pattern, {
664+
kEmptyObject,
665+
nocase: isMacOS || isWindows,
666+
windowsPathsNoEscape: true,
667+
nonegate: true,
668+
nocomment: true,
669+
optimizationLevel: 2,
670+
platform: windows ? 'win32' : 'posix',
671+
nocaseMagicOnly: true,
672+
});
673+
}
674+
653675
module.exports = {
654676
__proto__: null,
655677
Glob,
678+
matchGlobPattern,
656679
};

lib/internal/test_runner/coverage.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const {
2727
} = require('fs');
2828
const { setupCoverageHooks } = require('internal/util');
2929
const { tmpdir } = require('os');
30-
const { join, resolve, relative, matchesGlob } = require('path');
30+
const { join, resolve, relative } = require('path');
3131
const { fileURLToPath } = require('internal/url');
3232
const { kMappings, SourceMap } = require('internal/source_map/source_map');
3333
const {
@@ -36,6 +36,8 @@ const {
3636
ERR_SOURCE_MAP_MISSING_SOURCE,
3737
},
3838
} = require('internal/errors');
39+
const { matchGlobPattern } = require('internal/fs/glob');
40+
3941
const kCoverageFileRegex = /^coverage-(\d+)-(\d{13})-(\d+)\.json$/;
4042
const kIgnoreRegex = /\/\* node:coverage ignore next (?<count>\d+ )?\*\//;
4143
const kLineEndingRegex = /\r?\n$/u;
@@ -464,19 +466,24 @@ class TestCoverage {
464466
coverageExcludeGlobs: excludeGlobs,
465467
coverageIncludeGlobs: includeGlobs,
466468
} = this.options;
469+
467470
// This check filters out files that match the exclude globs.
468471
if (excludeGlobs?.length > 0) {
469472
for (let i = 0; i < excludeGlobs.length; ++i) {
470-
if (matchesGlob(relativePath, excludeGlobs[i]) ||
471-
matchesGlob(absolutePath, excludeGlobs[i])) return true;
473+
if (
474+
matchGlobPattern(relativePath, excludeGlobs[i]) ||
475+
matchGlobPattern(absolutePath, excludeGlobs[i])
476+
) return true;
472477
}
473478
}
474479

475480
// This check filters out files that do not match the include globs.
476481
if (includeGlobs?.length > 0) {
477482
for (let i = 0; i < includeGlobs.length; ++i) {
478-
if (matchesGlob(relativePath, includeGlobs[i]) ||
479-
matchesGlob(absolutePath, includeGlobs[i])) return false;
483+
if (
484+
matchGlobPattern(relativePath, includeGlobs[i]) ||
485+
matchGlobPattern(absolutePath, includeGlobs[i])
486+
) return false;
480487
}
481488
return true;
482489
}

lib/internal/test_runner/utils.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,11 @@ function parseCommandLine() {
287287

288288
if (coverage) {
289289
coverageExcludeGlobs = getOptionValue('--test-coverage-exclude');
290+
if (!coverageExcludeGlobs || coverageExcludeGlobs.length === 0) {
291+
// TODO(pmarchini): this default should follow something similar to c8 defaults
292+
// Default exclusions should be also exported to be used by other tools / users
293+
coverageExcludeGlobs = [kDefaultPattern];
294+
}
290295
coverageIncludeGlobs = getOptionValue('--test-coverage-include');
291296

292297
branchCoverage = getOptionValue('--test-coverage-branches');

lib/path.js

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,12 @@ const {
5252
} = require('internal/validators');
5353

5454
const {
55-
getLazy,
5655
emitExperimentalWarning,
5756
isWindows,
58-
isMacOS,
57+
getLazy,
5958
} = require('internal/util');
6059

61-
const lazyMinimatch = getLazy(() => require('internal/deps/minimatch/index'));
60+
const lazyMatchGlobPattern = getLazy(() => require('internal/fs/glob').matchGlobPattern);
6261

6362
function isPathSeparator(code) {
6463
return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
@@ -164,22 +163,6 @@ function _format(sep, pathObject) {
164163
return dir === pathObject.root ? `${dir}${base}` : `${dir}${sep}${base}`;
165164
}
166165

167-
function glob(path, pattern, windows) {
168-
emitExperimentalWarning('glob');
169-
validateString(path, 'path');
170-
validateString(pattern, 'pattern');
171-
return lazyMinimatch().minimatch(path, pattern, {
172-
__proto__: null,
173-
nocase: isMacOS || isWindows,
174-
windowsPathsNoEscape: true,
175-
nonegate: true,
176-
nocomment: true,
177-
optimizationLevel: 2,
178-
platform: windows ? 'win32' : 'posix',
179-
nocaseMagicOnly: true,
180-
});
181-
}
182-
183166
const win32 = {
184167
/**
185168
* path.resolve([from ...], to)
@@ -1140,7 +1123,8 @@ const win32 = {
11401123
},
11411124

11421125
matchesGlob(path, pattern) {
1143-
return glob(path, pattern, true);
1126+
emitExperimentalWarning('glob');
1127+
return lazyMatchGlobPattern()(path, pattern, true);
11441128
},
11451129

11461130
sep: '\\',
@@ -1616,7 +1600,8 @@ const posix = {
16161600
},
16171601

16181602
matchesGlob(path, pattern) {
1619-
return glob(path, pattern, false);
1603+
emitExperimentalWarning('glob');
1604+
return lazyMatchGlobPattern()(path, pattern, false);
16201605
},
16211606

16221607
sep: '/',
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const test = require('node:test');
2+
const assert = require('node:assert');
3+
const { foo } = require('./logic-file');
4+
5+
test('foo returns 1', () => {
6+
assert.strictEqual(foo(), 1);
7+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import test from 'node:test';
2+
import assert from 'node:assert';
3+
import { foo } from './logic-file.js';
4+
5+
test('foo returns 1', () => {
6+
assert.strictEqual(foo(), 1);
7+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import test from 'node:test';
2+
import assert from 'node:assert';
3+
import { foo } from './logic-file.js';
4+
5+
test('foo returns 1', () => {
6+
assert.strictEqual(foo(), 1);
7+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
function foo() {
2+
return 1;
3+
}
4+
5+
function bar() {
6+
return 'bar';
7+
}
8+
9+
module.exports = { foo, bar };

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy