TestContext
History
before function was added to TestContext.An instance of TestContext is passed to each test function in order to
interact with the test runner. However, the TestContext constructor is not
exposed as part of the API.
context.before(fn?, options?): void
Function | AsyncFunctionTestContext object. If the hook uses callbacks,
the callback function is passed as the second argument. Default: A no-op
function.ObjectAbortSignalnumberInfinity.This function registers a hook that runs before any subtests of the current test.
context.beforeEach(fn?, options?): void
Function | AsyncFunctionTestContext object. If the hook uses callbacks,
the callback function is passed as the second argument. Default: A no-op
function.ObjectAbortSignalnumberInfinity.This function registers a hook that runs before each subtest of the current test.
test('top level test', async (t) => { t.beforeEach((t) => t.diagnostic(`about to run ${t.name}`)); await t.test( 'This is a subtest', (t) => { // Some relevant assertion here }, ); });
context.after(fn?, options?): void
Function | AsyncFunctionTestContext object. If the hook uses callbacks,
the callback function is passed as the second argument. Default: A no-op
function.ObjectAbortSignalnumberInfinity.This function registers a hook that runs after the current test finishes.
test('top level test', async (t) => { t.after((t) => t.diagnostic(`finished running ${t.name}`)); // Some relevant assertion here });
context.afterEach(fn?, options?): void
Function | AsyncFunctionTestContext object. If the hook uses callbacks,
the callback function is passed as the second argument. Default: A no-op
function.ObjectAbortSignalnumberInfinity.This function registers a hook that runs after each subtest of the current test.
test('top level test', async (t) => { t.afterEach((t) => t.diagnostic(`finished running ${t.name}`)); await t.test( 'This is a subtest', (t) => { // Some relevant assertion here }, ); });
An object containing assertion methods bound to context. The top-level
functions from the node:assert module are exposed here for the purpose of
creating test plans.
test('test', (t) => { t.plan(1); t.assert.strictEqual(true, true); });
context.assert.fileSnapshot(value, path, options?): void
any--test-update-snapshots flag, the serialized value is written to
path. Otherwise, the serialized value is compared to the contents of the
existing snapshot file.stringvalue is written.ObjectArrayvalue into a string. value is passed as the only argument to the first
serializer function. The return value of each serializer is passed as input
to the next serializer. Once all serializers have run, the resulting value
is coerced to a string. Default: If no serializers are provided, the
test runner's default serializers are used.This function serializes value and writes it to the file specified by path.
test('snapshot test with default serialization', (t) => { t.assert.fileSnapshot({ value1: 1, value2: 2 }, './snapshots/snapshot.json'); });
This function differs from context.assert.snapshot() in the following ways:
- The snapshot file path is explicitly provided by the user.
- Each snapshot file is limited to a single snapshot value.
- No additional escaping is performed by the test runner.
These differences allow snapshot files to better support features such as syntax highlighting.
context.assert.snapshot(value, options?): void
any--test-update-snapshots flag, the serialized value is written to
the snapshot file. Otherwise, the serialized value is compared to the
corresponding value in the existing snapshot file.ObjectArrayvalue into a string. value is passed as the only argument to the first
serializer function. The return value of each serializer is passed as input
to the next serializer. Once all serializers have run, the resulting value
is coerced to a string. Default: If no serializers are provided, the
test runner's default serializers are used.This function implements assertions for snapshot testing.
test('snapshot test with default serialization', (t) => { t.assert.snapshot({ value1: 1, value2: 2 }); }); test('snapshot test with custom serialization', (t) => { t.assert.snapshot({ value3: 3, value4: 4 }, { serializers: [(value) => JSON.stringify(value)], }); });
context.diagnostic(message): void
stringThis function is used to write diagnostics to the output. Any diagnostic information is included at the end of the test's results. This function does not return a value.
test('top level test', (t) => { t.diagnostic('A diagnostic message'); });
context.log(message, data?): void
stringanyThis function is used to write a log message to the output. Unlike
context.diagnostic, the resulting 'test:log' event is emitted
immediately, in the order that the tests execute, rather than being buffered
until the test reports its results. This function does not return a value.
test('top level test', (t) => { t.log('fetched user', { userId: 42 }); t.log('retrying flaky endpoint', { attempt: 3 }); });
The absolute path of the test file that created the current test. If a test file imports additional modules that generate tests, the imported tests will return the path of the root test file.
The name of the test and each of its ancestors, separated by >.
The name of the test.
booleanfalse before the test is executed, e.g. in a beforeEach hook.Indicated whether the test succeeded.
The failure reason for the test/case; wrapped and available via context.error.cause.
numberThe attempt number of the test. This value is zero-based, so the first attempt is 0,
the second attempt is 1, and so on. This property is useful in conjunction with the
--test-rerun-failures option to determine which attempt the test is currently running.
string[]A frozen array of the test's flattened lowercased tags, in declaration order, including any tags inherited from ancestor suites. Empty when the test has no tags. See Test tags.
The unique identifier of the worker running the current test file. This value is
derived from the NODE_TEST_WORKER_ID environment variable. When running tests
with --test-isolation=process (the default), each test file runs in a separate
child process and is assigned a worker ID from 1 to N, where N is the number of
concurrent workers. When running with --test-isolation=none, all tests run in
the same process and the worker ID is always 1. This value is undefined when
not running in a test context.
This property is useful for splitting resources (like database connections or server ports) across concurrent test files:
import { test } from 'node:test'; import { process } from 'node:process'; test('database operations', async (t) => { // Worker ID is available via context console.log(`Running in worker ${t.workerId}`); // Or via environment variable (available at import time) const workerId = process.env.NODE_TEST_WORKER_ID; // Use workerId to allocate separate resources per worker });
context.plan
History
options parameter.context.plan(count, options?): void
This function is used to set the number of assertions and subtests that are expected to run within the test. If the number of assertions and subtests that run does not match the expected count, the test will fail.
Note: To make sure assertions are tracked,
t.assertmust be used instead ofassertdirectly.
test('top level test', (t) => { t.plan(2); t.assert.ok('some relevant assertion here'); t.test('subtest', () => {}); });
When working with asynchronous code, the plan function can be used to ensure that the
correct number of assertions are run:
test('planning with streams', (t, done) => { function* generate() { yield 'a'; yield 'b'; yield 'c'; } const expected = ['a', 'b', 'c']; t.plan(expected.length); const stream = Readable.from(generate()); stream.on('data', (chunk) => { t.assert.strictEqual(chunk, expected.shift()); }); stream.on('end', () => { done(); }); });
When using the wait option, you can control how long the test will wait for the expected assertions.
For example, setting a maximum wait time ensures that the test will wait for asynchronous assertions
to complete within the specified timeframe:
test('plan with wait: 2000 waits for async assertions', (t) => { t.plan(1, { wait: 2000 }); // Waits for up to 2 seconds for the assertion to complete. const asyncActivity = () => { setTimeout(() => { t.assert.ok(true, 'Async assertion completed within the wait time'); }, 1000); // Completes after 1 second, within the 2-second wait time. }; asyncActivity(); // The test will pass because the assertion is completed in time. });
Note: If a wait timeout is specified, it begins counting down only after the test function finishes executing.
context.runOnly(shouldRunOnlyTests): void
booleanonly tests.If shouldRunOnlyTests is truthy, the test context will only run tests that
have the only option set. Otherwise, all tests are run. If Node.js was not
started with the --test-only command-line option, this function is a
no-op.
test('top level test', (t) => { // The test context can be set to run subtests with the 'only' option. t.runOnly(true); return Promise.all([ t.test('this subtest is now skipped'), t.test('this subtest is run', { only: true }), ]); });
AbortSignalCan be used to abort test subtasks when the test has been aborted.
test('top level test', async (t) => { await fetch('some/uri', { signal: t.signal }); });
context.skip(message?): void
stringThis function causes the test's output to indicate the test as skipped. If
message is provided, it is included in the output. Calling skip() does
not terminate execution of the test function. This function does not return a
value.
test('top level test', (t) => { // Make sure to return here as well if the test contains additional logic. t.skip('this is skipped'); });
context.todo(message?): void
stringTODO message.This function adds a TODO directive to the test's output. If message is
provided, it is included in the output. Calling todo() does not terminate
execution of the test function. This function does not return a value.
test('top level test', (t) => { // This test is marked as `TODO` t.todo('this is a todo'); });
context.test
History
tags option.signal option.timeout option.context.test(name?, options?, fn?): Promise
stringname property of fn, or '<anonymous>' if
fn does not have a name.Objecttrue, it would run all subtests in parallel.
If false, it would only run one test at a time.
If unspecified, subtests inherit this value from their parent.
Default: null.booleanonly tests, then this test will be run. Otherwise, the test is skipped.
Default: false.AbortSignalfalse.string[]--experimental-test-tag-filter to filter which
tests run. Tags inherit from the parent test or suite by union. See
Test tags. Default: [].TODO. If a string
is provided, that string is displayed in the test results as the reason why
the test is TODO. Default: false.numberInfinity.numberundefined.Function | AsyncFunctionTestContext object. If the test uses callbacks,
the callback function is passed as the second argument. Default: A no-op
function.Promiseundefined once the test completes.This function is used to create subtests under the current test. This function
behaves in the same fashion as the top level test() function.
test('top level test', async (t) => { await t.test( 'This is a subtest', { only: false, skip: false, concurrency: 1, todo: false, plan: 1 }, (t) => { t.assert.ok('some relevant assertion here'); }, ); });
context.waitFor(condition, options?): Promise
Function | AsyncFunctionObjectPromisecondition.This method polls a condition function until that function either returns
successfully or the operation times out.