nodejs/node
Test runner
Owners: @nodejs/test_runner. Public docs at doc/api/test.md.
Purpose
Provide a built-in test framework — node --test and node:test — that runs without installing third-party packages: parallel execution, watch mode, mocking, snapshots, code coverage, TAP/dot/junit/spec reporters, and concurrency primitives.
Directory layout
lib/
test.js // public node:test module
test/
reporters.js // re-export of reporter modules
internal/test_runner/
runner.js // top-level driver: discover, spawn, aggregate
test.js // Test/Suite/Hook classes
harness.js // describe/it/before/after globals
coverage.js // V8 coverage integration
snapshot.js // snapshot module (toMatchSnapshot)
tests_stream.js // events stream consumed by reporters
utils.js // shared helpers
assert.js // strict-style assertion bridge
mock/ // mock module + module-mock
reporter/ // tap, dot, spec, junit, lcov reporters
lib/internal/main/test_runner.js // entry: node --test
lib/internal/main/watch_mode.js // entry: node --watch / --watch-path with --testKey abstractions
| Type / file | Role |
|---|---|
Test (lib/internal/test_runner/test.js) |
Single test or suite node in the tree. |
Suite (lib/internal/test_runner/test.js) |
Container test that holds children and hooks. |
TestContext (lib/internal/test_runner/test.js) |
t.test, t.before, t.diagnostic, t.runOnly, etc. given to test fns. |
Runner (lib/internal/test_runner/runner.js) |
Discovers files (matching --test-name-pattern etc.), spawns child Nodes. |
TestsStream (lib/internal/test_runner/tests_stream.js) |
Readable that emits TAP-shape events. |
Reporters (lib/internal/test_runner/reporter/) |
Subscribe to TestsStream and emit text. |
MockModule (lib/internal/test_runner/mock/) |
t.mock.module(specifier) implementation. |
Coverage (lib/internal/test_runner/coverage.js) |
Wraps V8 coverage and produces lcov/text/json reports. |
How it works
sequenceDiagram
participant CLI as node --test [paths]
participant Runner as Runner
participant Discover as discover files
participant Worker as Worker / fork per file
participant Stream as TestsStream
participant Reporter as TAP / spec / lcov
CLI->>Runner: lib/internal/main/test_runner.js
Runner->>Discover: glob test files
Discover-->>Runner: file list
loop per concurrency
Runner->>Worker: spawn child Node, --test-isolation=process
Worker-->>Stream: emit start/pass/fail/diagnostic
end
Stream->>Reporter: pipe events
Reporter-->>CLI: stdoutWithout --test-isolation=process, all tests run in the parent Node process; --test-isolation=process (the default in 22+) spawns one Node child per file. Watch mode (--watch) re-runs only the affected files when their dependency graph changes (graph derived from CJS require.cache and ESM module map).
Mocking
t.mock provides:
t.mock.fn(impl)— function mock with call tracking.t.mock.method(obj, name, impl)— replace a method.t.mock.timers.enable({ apis: ['setTimeout', 'setInterval', ...] })— fake timers.t.mock.module(specifier, opts)— replace a module's exports for the duration of the test (uses themodule.registerhooks).
The module-mock implementation (lib/internal/test_runner/mock/module.js) registers a customization-hook layer that intercepts import/require to swap the target module.
Coverage
--experimental-test-coverage enables V8 coverage collection. lib/internal/test_runner/coverage.js:
- Calls
inspectorProfiler.startPreciseCoverage. - Maps V8 coverage ranges back to source coordinates.
- Emits lcov/text/json/junit-coverage reports.
The legacy c8 integration is documented in doc/api/test.md.
Snapshots
t.assert.snapshot (and t.toMatchSnapshot) live in lib/internal/test_runner/snapshot.js. Serialised values get diffed against a *.snapshot file next to the test file; --test-update-snapshots rewrites them.
Reporters
Each reporter is a Transform stream from TestsStream's structured events to text. Supported: tap (default), dot, spec, junit, lcov (for coverage). Custom reporters are written as transforms exported by user modules.
Integration points
- Module loaders: mocking integrates with
module.register; watch mode reads the loader's module graph. - Inspector / V8 profiler: coverage uses the Inspector API.
- Streams:
TestsStreamis a regularReadable. - Worker threads: tests can spin up workers; the runner does not by itself.
Entry points for modification
- New reporter? Add a module under
lib/internal/test_runner/reporter/and register it inlib/test/reporters.js. - New mock primitive?
lib/internal/test_runner/mock/. - Change discovery behaviour?
lib/internal/test_runner/runner.js#parseCommandLineandglob. - Affected tests live at
test/parallel/test-runner-*.jsandtest/test-runner/.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.