Skip to content

Commit aecf0ed

Browse files
cjihrigMoLow
andcommitted
test_runner: support running tests in process
This commit introduces a new --experimental-test-isolation flag that, when set to 'none', causes the test runner to execute all tests in the same process. By default, this is the main test runner process, but if watch mode is enabled, it spawns a separate process that runs all of the tests. The default value of the new flag is 'process', which uses the existing behavior of running each test file in its own child process. It is worth noting that when the isolation mode is 'none', globals and all other top level logic (such as top level before() and after() hooks) is shared among all files. Co-authored-by: Moshe Atlow <[email protected]>
1 parent a341d6e commit aecf0ed

22 files changed

+741
-205
lines changed

doc/api/cli.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,20 @@ generated as part of the test runner output. If no tests are run, a coverage
10911091
report is not generated. See the documentation on
10921092
[collecting code coverage from tests][] for more details.
10931093

1094+
### `--experimental-test-isolation=mode`
1095+
1096+
<!-- YAML
1097+
added: REPLACEME
1098+
-->
1099+
1100+
> Stability: 1.0 - Early development
1101+
1102+
Configures the type of test isolation used in the test runner. When `mode` is
1103+
`'process'`, each test file is run in a separate child process. When `mode` is
1104+
`'none'`, all test files run in the same process as the test runner. The default
1105+
isolation mode is `'process'`. This flag is ignored if the `--test` flag is not
1106+
present.
1107+
10941108
### `--experimental-test-module-mocks`
10951109

10961110
<!-- YAML
@@ -2196,7 +2210,9 @@ added:
21962210
-->
21972211

21982212
The maximum number of test files that the test runner CLI will execute
2199-
concurrently. The default value is `os.availableParallelism() - 1`.
2213+
concurrently. If `--experimental-test-isolation` is set to `'none'`, this flag
2214+
is ignored and concurrency is one. Otherwise, concurrency defaults to
2215+
`os.availableParallelism() - 1`.
22002216

22012217
### `--test-coverage-exclude`
22022218

@@ -2361,7 +2377,7 @@ added: v22.3.0
23612377

23622378
> Stability: 1.0 - Early development
23632379
2364-
Regenerates the snapshot file used by the test runner for [snapshot testing][].
2380+
Regenerates the snapshot files used by the test runner for [snapshot testing][].
23652381
Node.js must be started with the `--experimental-test-snapshots` flag in order
23662382
to use this functionality.
23672383

doc/api/test.md

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -445,18 +445,22 @@ in the [test runner execution model][] section.
445445

446446
### Test runner execution model
447447

448-
Each matching test file is executed in a separate child process. The maximum
449-
number of child processes running at any time is controlled by the
450-
[`--test-concurrency`][] flag. If the child process finishes with an exit code
451-
of 0, the test is considered passing. Otherwise, the test is considered to be a
452-
failure. Test files must be executable by Node.js, but are not required to use
453-
the `node:test` module internally.
448+
When process-level test isolation is enabled, each matching test file is
449+
executed in a separate child process. The maximum number of child processes
450+
running at any time is controlled by the [`--test-concurrency`][] flag. If the
451+
child process finishes with an exit code of 0, the test is considered passing.
452+
Otherwise, the test is considered to be a failure. Test files must be executable
453+
by Node.js, but are not required to use the `node:test` module internally.
454454

455455
Each test file is executed as if it was a regular script. That is, if the test
456456
file itself uses `node:test` to define tests, all of those tests will be
457457
executed within a single application thread, regardless of the value of the
458458
`concurrency` option of [`test()`][].
459459

460+
When process-level test isolation is disabled, each matching test file is
461+
imported into the test runner process. Once all test files have been loaded, the
462+
top level tests are executed with a concurrency of one.
463+
460464
## Collecting code coverage
461465

462466
> Stability: 1 - Experimental
@@ -933,7 +937,7 @@ the [`--experimental-test-snapshots`][] command-line flag.
933937
Snapshot files are generated by starting Node.js with the
934938
[`--test-update-snapshots`][] command-line flag. A separate snapshot file is
935939
generated for each test file. By default, the snapshot file has the same name
936-
as `process.argv[1]` with a `.snapshot` file extension. This behavior can be
940+
as the test file with a `.snapshot` file extension. This behavior can be
937941
configured using the `snapshot.setResolveSnapshotPath()` function. Each
938942
snapshot assertion corresponds to an export in the snapshot file.
939943

@@ -1239,6 +1243,9 @@ added:
12391243
- v18.9.0
12401244
- v16.19.0
12411245
changes:
1246+
- version: REPLACEME
1247+
pr-url: https://github.com/nodejs/node/pull/53927
1248+
description: Added the `isolation` option.
12421249
- version: v22.6.0
12431250
pr-url: https://github.com/nodejs/node/pull/53866
12441251
description: Added the `globPatterns` option.
@@ -1274,8 +1281,13 @@ changes:
12741281
* `inspectPort` {number|Function} Sets inspector port of test child process.
12751282
This can be a number, or a function that takes no arguments and returns a
12761283
number. If a nullish value is provided, each process gets its own port,
1277-
incremented from the primary's `process.debugPort`.
1278-
**Default:** `undefined`.
1284+
incremented from the primary's `process.debugPort`. This option is ignored
1285+
if the `isolation` option is set to `'none'` as no child processes are
1286+
spawned. **Default:** `undefined`.
1287+
* `isolation` {string} Configures the type of test isolation. If set to
1288+
`'process'`, each test file is run in a separate child process. If set to
1289+
`'none'`, all test files run in the current process. The default isolation
1290+
mode is `'process'`.
12791291
* `only`: {boolean} If truthy, the test context will only run tests that
12801292
have the `only` option set
12811293
* `setup` {Function} A function that accepts the `TestsStream` instance
@@ -1727,9 +1739,9 @@ added: v22.3.0
17271739
17281740
* `fn` {Function} A function used to compute the location of the snapshot file.
17291741
The function receives the path of the test file as its only argument. If the
1730-
`process.argv[1]` is not associated with a file (for example in the REPL),
1731-
the input is undefined. `fn()` must return a string specifying the location of
1732-
the snapshot file.
1742+
test is not associated with a file (for example in the REPL), the input is
1743+
undefined. `fn()` must return a string specifying the location of the snapshot
1744+
snapshot file.
17331745

17341746
This function is used to customize the location of the snapshot file used for
17351747
snapshot testing. By default, the snapshot filename is the same as the entry

doc/node.1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ Enable the experimental node:sqlite module.
185185
.It Fl -experimental-test-coverage
186186
Enable code coverage in the test runner.
187187
.
188+
.It Fl -experimental-test-isolation Ns = Ns Ar mode
189+
Configures the type of test isolation used in the test runner.
190+
.
188191
.It Fl -experimental-test-module-mocks
189192
Enable module mocking in the test runner.
190193
.

lib/internal/main/test_runner.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ markBootstrapComplete();
2121

2222
const options = parseCommandLine();
2323

24-
if (isUsingInspector()) {
24+
if (isUsingInspector() && options.isolation === 'process') {
2525
process.emitWarning('Using the inspector with --test forces running at a concurrency of 1. ' +
2626
'Use the inspectPort option to run with concurrency');
2727
options.concurrency = 1;

lib/internal/test_runner/harness.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,4 +334,5 @@ module.exports = {
334334
after: hook('after'),
335335
beforeEach: hook('beforeEach'),
336336
afterEach: hook('afterEach'),
337+
startSubtestAfterBootstrap,
337338
};

0 commit comments

Comments
 (0)