Test runner#
Source Code:lib/test.js
Thenode:test module facilitates the creation of JavaScript tests.To access it:
import testfrom'node:test';const test =require('node:test');
This module is only available under thenode: scheme. The following will notwork:
import testfrom'test';const test =require('test');
Tests created via thetest module consist of a single function that isprocessed in one of three ways:
- A synchronous function that is considered failing if it throws an exception,and is considered passing otherwise.
- A function that returns a
Promisethat is considered failing if thePromiserejects, and is considered passing if thePromiseresolves. - A function that receives a callback function. If the callback receives anytruthy value as its first argument, the test is considered failing. If afalsy value is passed as the first argument to the callback, the test isconsidered passing. If the test function receives a callback function andalso returns a
Promise, the test will fail.
The following example illustrates how tests are written using thetest module.
test('synchronous passing test',(t) => {// This test passes because it does not throw an exception. assert.strictEqual(1,1);});test('synchronous failing test',(t) => {// This test fails because it throws an exception. assert.strictEqual(1,2);});test('asynchronous passing test',async (t) => {// This test passes because the Promise returned by the async// function is not rejected. assert.strictEqual(1,1);});test('asynchronous failing test',async (t) => {// This test fails because the Promise returned by the async// function is rejected. assert.strictEqual(1,2);});test('failing test using Promises',(t) => {// Promises can be used directly as well.returnnewPromise((resolve, reject) => {setImmediate(() => {reject(newError('this will cause the test to fail')); }); });});test('callback passing test',(t, done) => {// done() is the callback function. When the setImmediate() runs, it invokes// done() with no arguments.setImmediate(done);});test('callback failing test',(t, done) => {// When the setImmediate() runs, done() is invoked with an Error object and// the test fails.setImmediate(() => {done(newError('callback failure')); });});If any tests fail, the process exit code is set to1.
Subtests#
The test context'stest() method allows subtests to be created. This methodbehaves identically to the top leveltest() function. The following exampledemonstrates the creation of a top level test with two subtests.
test('top level test',async (t) => {await t.test('subtest 1',(t) => { assert.strictEqual(1,1); });await t.test('subtest 2',(t) => { assert.strictEqual(2,2); });});In this example,await is used to ensure that both subtests have completed.This is necessary because parent tests do not wait for their subtests tocomplete. Any subtests that are still outstanding when their parent finishesare cancelled and treated as failures. Any subtest failures cause the parenttest to fail.
Skipping tests#
Individual tests can be skipped by passing theskip option to the test, or bycalling the test context'sskip() method as shown in thefollowing example.
// The skip option is used, but no message is provided.test('skip option', {skip:true },(t) => {// This code is never executed.});// The skip option is used, and a message is provided.test('skip option with message', {skip:'this is skipped' },(t) => {// This code is never executed.});test('skip() method',(t) => {// Make sure to return here as well if the test contains additional logic. t.skip();});test('skip() method with message',(t) => {// Make sure to return here as well if the test contains additional logic. t.skip('this is skipped');});describe/it syntax#
Running tests can also be done usingdescribe to declare a suiteandit to declare a test.A suite is used to organize and group related tests together.it is a shorthand fortest().
describe('A thing',() => {it('should work',() => { assert.strictEqual(1,1); });it('should be ok',() => { assert.strictEqual(2,2); });describe('a nested thing',() => {it('should work',() => { assert.strictEqual(3,3); }); });});describe andit are imported from thenode:test module.
import { describe, it }from'node:test';const { describe, it } =require('node:test');
only tests#
If Node.js is started with the--test-only command-line option, it ispossible to skip all top level tests except for a selected subset by passingtheonly option to the tests that should be run. When a test with theonlyoption set is run, all subtests are also run. The test context'srunOnly()method can be used to implement the same behavior at the subtest level.
// Assume Node.js is run with the --test-only command-line option.// The 'only' option is set, so this test is run.test('this test is run', {only:true },async (t) => {// Within this test, all subtests are run by default.await t.test('running subtest');// The test context can be updated to run subtests with the 'only' option. t.runOnly(true);await t.test('this subtest is now skipped');await t.test('this subtest is run', {only:true });// Switch the context back to execute all tests. t.runOnly(false);await t.test('this subtest is now run');// Explicitly do not run these tests.await t.test('skipped subtest 3', {only:false });await t.test('skipped subtest 4', {skip:true });});// The 'only' option is not set, so this test is skipped.test('this test is not run',() => {// This code is not run.thrownewError('fail');});Filtering tests by name#
The--test-name-pattern command-line option can be used to only run testswhose name matches the provided pattern. Test name patterns are interpreted asJavaScript regular expressions. The--test-name-pattern option can bespecified multiple times in order to run nested tests. For each test that isexecuted, any corresponding test hooks, such asbeforeEach(), are alsorun.
Given the following test file, starting Node.js with the--test-name-pattern="test [1-3]" option would cause the test runner to executetest 1,test 2, andtest 3. Iftest 1 did not match the test namepattern, then its subtests would not execute, despite matching the pattern. Thesame set of tests could also be executed by passing--test-name-patternmultiple times (e.g.--test-name-pattern="test 1",--test-name-pattern="test 2", etc.).
test('test 1',async (t) => {await t.test('test 2');await t.test('test 3');});test('Test 4',async (t) => {await t.test('Test 5');await t.test('test 6');});Test name patterns can also be specified using regular expression literals. Thisallows regular expression flags to be used. In the previous example, startingNode.js with--test-name-pattern="/test [4-5]/i" would matchTest 4 andTest 5 because the pattern is case-insensitive.
Test name patterns do not change the set of files that the test runner executes.
Extraneous asynchronous activity#
Once a test function finishes executing, the results are reported as quicklyas possible while maintaining the order of the tests. However, it is possiblefor the test function to generate asynchronous activity that outlives the testitself. The test runner handles this type of activity, but does not delay thereporting of test results in order to accommodate it.
In the following example, a test completes with twosetImmediate()operations still outstanding. The firstsetImmediate() attempts to create anew subtest. Because the parent test has already finished and output itsresults, the new subtest is immediately marked as failed, and reported laterto the<TestsStream>.
The secondsetImmediate() creates anuncaughtException event.uncaughtException andunhandledRejection events originating from a completedtest are marked as failed by thetest module and reported as diagnosticwarnings at the top level by the<TestsStream>.
test('a test that creates asynchronous activity',(t) => {setImmediate(() => { t.test('subtest that is created too late',(t) => {thrownewError('error1'); }); });setImmediate(() => {thrownewError('error2'); });// The test finishes after this line.});Watch mode#
The Node.js test runner supports running in watch mode by passing the--watch flag:
node --test --watchIn watch mode, the test runner will watch for changes to test files andtheir dependencies. When a change is detected, the test runner willrerun the tests affected by the change.The test runner will continue to run until the process is terminated.
Running tests from the command line#
The Node.js test runner can be invoked from the command line by passing the--test flag:
node --testBy default, Node.js will recursively search the current directory forJavaScript source files matching a specific naming convention. Matching filesare executed as test files. More information on the expected test file namingconvention and behavior can be found in thetest runner execution modelsection.
Alternatively, one or more paths can be provided as the final argument(s) tothe Node.js command, as shown below.
node --test test1.js test2.mjs custom_test_dir/In this example, the test runner will execute the filestest1.js andtest2.mjs. The test runner will also recursively search thecustom_test_dir/ directory for test files to execute.
Test runner execution model#
When searching for test files to execute, the test runner behaves as follows:
- Any files explicitly provided by the user are executed.
- If the user did not explicitly specify any paths, the current workingdirectory is recursively searched for files as specified in the followingsteps.
node_modulesdirectories are skipped unless explicitly provided by theuser.- If a directory named
testis encountered, the test runner will search itrecursively for all all.js,.cjs, and.mjsfiles. All of these filesare treated as test files, and do not need to match the specific namingconvention detailed below. This is to accommodate projects that place all oftheir tests in a singletestdirectory. - In all other directories,
.js,.cjs, and.mjsfiles matching thefollowing patterns are treated as test files:^test$- Files whose basename is the string'test'. Examples:test.js,test.cjs,test.mjs.^test-.+- Files whose basename starts with the string'test-'followed by one or more characters. Examples:test-example.js,test-another-example.mjs..+[\.\-\_]test$- Files whose basename ends with.test,-test, or_test, preceded by one or more characters. Examples:example.test.js,example-test.cjs,example_test.mjs.- Other file types understood by Node.js such as
.nodeand.jsonare notautomatically executed by the test runner, but are supported if explicitlyprovided on the command line.
Each matching test file is executed in a separate child process. The maximumnumber of child processes running at any time is controlled by the--test-concurrency flag. If the child process finishes with an exit codeof 0, the test is considered passing. Otherwise, the test is considered to be afailure. Test files must be executable by Node.js, but are not required to usethenode:test module internally.
Each test file is executed as if it was a regular script. That is, if the testfile itself usesnode:test to define tests, all of those tests will beexecuted within a single application thread, regardless of the value of theconcurrency option oftest().
Collecting code coverage#
When Node.js is started with the--experimental-test-coveragecommand-line flag, code coverage is collected and statistics are reported onceall tests have completed. If theNODE_V8_COVERAGE environment variable isused to specify a code coverage directory, the generated V8 coverage files arewritten to that directory. Node.js core modules and files withinnode_modules/ directories are not included in the coverage report. Ifcoverage is enabled, the coverage report is sent to anytest reporters viathe'test:coverage' event.
Coverage can be disabled on a series of lines using the followingcomment syntax:
/* node:coverage disable */if (anAlwaysFalseCondition) {// Code in this branch will never be executed, but the lines are ignored for// coverage purposes. All lines following the 'disable' comment are ignored// until a corresponding 'enable' comment is encountered.console.log('this is never executed');}/* node:coverage enable */Coverage can also be disabled for a specified number of lines. After thespecified number of lines, coverage will be automatically reenabled. If thenumber of lines is not explicitly provided, a single line is ignored.
/* node:coverage ignore next */if (anAlwaysFalseCondition) {console.log('this is never executed'); }/* node:coverage ignore next 3 */if (anAlwaysFalseCondition) {console.log('this is never executed');}The test runner's code coverage functionality has the following limitations,which will be addressed in a future Node.js release:
- Source maps are not supported.
- Excluding specific files or directories from the coverage report is notsupported.
Mocking#
Thenode:test module supports mocking during testing via a top-levelmockobject. The following example creates a spy on a function that adds two numberstogether. The spy is then used to assert that the function was called asexpected.
import assertfrom'node:assert';import { mock, test }from'node:test';test('spies on a function',() => {const sum = mock.fn((a, b) => {return a + b; }); assert.strictEqual(sum.mock.calls.length,0); assert.strictEqual(sum(3,4),7); assert.strictEqual(sum.mock.calls.length,1);const call = sum.mock.calls[0]; assert.deepStrictEqual(call.arguments, [3,4]); assert.strictEqual(call.result,7); assert.strictEqual(call.error,undefined);// Reset the globally tracked mocks. mock.reset();});'use strict';const assert =require('node:assert');const { mock, test } =require('node:test');test('spies on a function',() => {const sum = mock.fn((a, b) => {return a + b; }); assert.strictEqual(sum.mock.calls.length,0); assert.strictEqual(sum(3,4),7); assert.strictEqual(sum.mock.calls.length,1);const call = sum.mock.calls[0]; assert.deepStrictEqual(call.arguments, [3,4]); assert.strictEqual(call.result,7); assert.strictEqual(call.error,undefined);// Reset the globally tracked mocks. mock.reset();});
The same mocking functionality is also exposed on theTestContext objectof each test. The following example creates a spy on an object method using theAPI exposed on theTestContext. The benefit of mocking via the test context isthat the test runner will automatically restore all mocked functionality oncethe test finishes.
test('spies on an object method',(t) => {const number = {value:5,add(a) {returnthis.value + a; }, }; t.mock.method(number,'add'); assert.strictEqual(number.add.mock.calls.length,0); assert.strictEqual(number.add(3),8); assert.strictEqual(number.add.mock.calls.length,1);const call = number.add.mock.calls[0]; assert.deepStrictEqual(call.arguments, [3]); assert.strictEqual(call.result,8); assert.strictEqual(call.target,undefined); assert.strictEqual(call.this, number);});Timers#
Mocking timers is a technique commonly used in software testing to simulate andcontrol the behavior of timers, such assetInterval andsetTimeout,without actually waiting for the specified time intervals.
Refer to theMockTimers class for a full list of methods and features.
This allows developers to write more reliable andpredictable tests for time-dependent functionality.
The example below shows how to mocksetTimeout.Using.enable(['setTimeout']);it will mock thesetTimeout functions in thenode:timers andnode:timers/promises modules,as well as from the Node.js global context.
Note: Destructuring functions such asimport { setTimeout } from 'node:timers'is currently not supported by this API.
import assertfrom'node:assert';import { mock, test }from'node:test';test('mocks setTimeout to be executed synchronously without having to actually wait for it',() => {const fn = mock.fn();// Optionally choose what to mock mock.timers.enable(['setTimeout']);setTimeout(fn,9999); assert.strictEqual(fn.mock.callCount(),0);// Advance in time mock.timers.tick(9999); assert.strictEqual(fn.mock.callCount(),1);// Reset the globally tracked mocks. mock.timers.reset();// If you call reset mock instance, it will also reset timers instance mock.reset();});const assert =require('node:assert');const { mock, test } =require('node:test');test('mocks setTimeout to be executed synchronously without having to actually wait for it',() => {const fn = mock.fn();// Optionally choose what to mock mock.timers.enable(['setTimeout']);setTimeout(fn,9999); assert.strictEqual(fn.mock.callCount(),0);// Advance in time mock.timers.tick(9999); assert.strictEqual(fn.mock.callCount(),1);// Reset the globally tracked mocks. mock.timers.reset();// If you call reset mock instance, it'll also reset timers instance mock.reset();});The same mocking functionality is also exposed in the mock property on theTestContext objectof each test. The benefit of mocking via the test context isthat the test runner will automatically restore all mocked timersfunctionality once the test finishes.
import assertfrom'node:assert';import { test }from'node:test';test('mocks setTimeout to be executed synchronously without having to actually wait for it',(context) => {const fn = context.mock.fn();// Optionally choose what to mock context.mock.timers.enable(['setTimeout']);setTimeout(fn,9999); assert.strictEqual(fn.mock.callCount(),0);// Advance in time context.mock.timers.tick(9999); assert.strictEqual(fn.mock.callCount(),1);});const assert =require('node:assert');const { test } =require('node:test');test('mocks setTimeout to be executed synchronously without having to actually wait for it',(context) => {const fn = context.mock.fn();// Optionally choose what to mock context.mock.timers.enable(['setTimeout']);setTimeout(fn,9999); assert.strictEqual(fn.mock.callCount(),0);// Advance in time context.mock.timers.tick(9999); assert.strictEqual(fn.mock.callCount(),1);});Test reporters#
History
| Version | Changes |
|---|---|
| v18.17.0 | Reporters are now exposed at |
| v18.15.0 | Added in: v18.15.0 |
Thenode:test module supports passing--test-reporterflags for the test runner to use a specific reporter.
The following built-reporters are supported:
tapThetapreporter outputs the test results in theTAP format.specThespecreporter outputs the test results in a human-readable format.dotThedotreporter outputs the test results in a compact format,where each passing test is represented by a.,and each failing test is represented by aX.junitThe junit reporter outputs test results in a jUnit XML format
Whenstdout is aTTY, thespec reporter is used by default.Otherwise, thetap reporter is used by default.
The reporters are available via thenode:test/reporters module:
import { tap, spec, dot, junit }from'node:test/reporters';const { tap, spec, dot, junit } =require('node:test/reporters');
Custom reporters#
--test-reporter can be used to specify a path to custom reporter.A custom reporter is a module that exports a valueaccepted bystream.compose.Reporters should transform events emitted by a<TestsStream>
Example of a custom reporter using<stream.Transform>:
import {Transform }from'node:stream';const customReporter =newTransform({writableObjectMode:true,transform(event, encoding, callback) {switch (event.type) {case'test:dequeue':callback(null,`test${event.data.name} dequeued`);break;case'test:enqueue':callback(null,`test${event.data.name} enqueued`);break;case'test:watch:drained':callback(null,'test watch queue drained');break;case'test:start':callback(null,`test${event.data.name} started`);break;case'test:pass':callback(null,`test${event.data.name} passed`);break;case'test:fail':callback(null,`test${event.data.name} failed`);break;case'test:plan':callback(null,'test plan');break;case'test:diagnostic':case'test:stderr':case'test:stdout':callback(null, event.data.message);break;case'test:coverage': {const { totalLineCount } = event.data.summary.totals;callback(null,`total line count:${totalLineCount}\n`);break; } } },});exportdefault customReporter;const {Transform } =require('node:stream');const customReporter =newTransform({writableObjectMode:true,transform(event, encoding, callback) {switch (event.type) {case'test:dequeue':callback(null,`test${event.data.name} dequeued`);break;case'test:enqueue':callback(null,`test${event.data.name} enqueued`);break;case'test:watch:drained':callback(null,'test watch queue drained');break;case'test:start':callback(null,`test${event.data.name} started`);break;case'test:pass':callback(null,`test${event.data.name} passed`);break;case'test:fail':callback(null,`test${event.data.name} failed`);break;case'test:plan':callback(null,'test plan');break;case'test:diagnostic':case'test:stderr':case'test:stdout':callback(null, event.data.message);break;case'test:coverage': {const { totalLineCount } = event.data.summary.totals;callback(null,`total line count:${totalLineCount}\n`);break; } } },});module.exports = customReporter;
Example of a custom reporter using a generator function:
exportdefaultasyncfunction *customReporter(source) {forawait (const eventof source) {switch (event.type) {case'test:dequeue':yield`test${event.data.name} dequeued`;break;case'test:enqueue':yield`test${event.data.name} enqueued`;break;case'test:watch:drained':yield'test watch queue drained';break;case'test:start':yield`test${event.data.name} started\n`;break;case'test:pass':yield`test${event.data.name} passed\n`;break;case'test:fail':yield`test${event.data.name} failed\n`;break;case'test:plan':yield'test plan';break;case'test:diagnostic':case'test:stderr':case'test:stdout':yield`${event.data.message}\n`;break;case'test:coverage': {const { totalLineCount } = event.data.summary.totals;yield`total line count:${totalLineCount}\n`;break; } } }}module.exports =asyncfunction *customReporter(source) {forawait (const eventof source) {switch (event.type) {case'test:dequeue':yield`test${event.data.name} dequeued`;break;case'test:enqueue':yield`test${event.data.name} enqueued`;break;case'test:watch:drained':yield'test watch queue drained';break;case'test:start':yield`test${event.data.name} started\n`;break;case'test:pass':yield`test${event.data.name} passed\n`;break;case'test:fail':yield`test${event.data.name} failed\n`;break;case'test:plan':yield'test plan\n';break;case'test:diagnostic':case'test:stderr':case'test:stdout':yield`${event.data.message}\n`;break;case'test:coverage': {const { totalLineCount } = event.data.summary.totals;yield`total line count:${totalLineCount}\n`;break; } } }};
The value provided to--test-reporter should be a string like one used in animport() in JavaScript code.
Multiple reporters#
The--test-reporter flag can be specified multiple times to report testresults in several formats. In this situationit is required to specify a destination for each reporterusing--test-reporter-destination.Destination can bestdout,stderr, or a file path.Reporters and destinations are paired accordingto the order they were specified.
In the following example, thespec reporter will output tostdout,and thedot reporter will output tofile.txt:
node --test-reporter=spec --test-reporter=dot --test-reporter-destination=stdout --test-reporter-destination=file.txtWhen a single reporter is specified, the destination will default tostdout,unless a destination is explicitly provided.
run([options])#
History
| Version | Changes |
|---|---|
| v18.17.0 | Add a testNamePatterns option. |
| v18.9.0 | Added in: v18.9.0 |
options<Object> Configuration options for running tests. The followingproperties are supported:concurrency<number> |<boolean> If a number is provided,then that many test processes would run in parallel, where each processcorresponds to one test file.Iftrue, it would runos.availableParallelism() - 1test files inparallel.Iffalse, it would only run one test file at a time.Default:false.files:<Array> An array containing the list of files to run.Default matching files fromtest runner execution model.inspectPort<number> |<Function> Sets inspector port of test child process.This can be a number, or a function that takes no arguments and returns anumber. If a nullish value is provided, each process gets its own port,incremented from the primary'sprocess.debugPort.Default:undefined.only:<boolean> If truthy, the test context will only run tests thathave theonlyoption setsetup<Function> A function that accepts theTestsStreaminstanceand can be used to setup listeners before any tests are run.Default:undefined.signal<AbortSignal> Allows aborting an in-progress test execution.testNamePatterns<string> |<RegExp> |<Array> A String, RegExp or a RegExp Array,that can be used to only run tests whose name matches the provided pattern.Test name patterns are interpreted as JavaScript regular expressions.For each test that is executed, any corresponding test hooks, such asbeforeEach(), are also run.Default:undefined.timeout<number> A number of milliseconds the test execution willfail after.If unspecified, subtests inherit this value from their parent.Default:Infinity.watch<boolean> Whether to run in watch mode or not.Default:false.shard<Object> Running tests in a specific shard.Default:undefined.
- Returns:<TestsStream>
import { tap }from'node:test/reporters';import processfrom'node:process';run({files: [path.resolve('./tests/test.js')] }) .compose(tap) .pipe(process.stdout);const { tap } =require('node:test/reporters');run({files: [path.resolve('./tests/test.js')] }) .compose(tap) .pipe(process.stdout);
test([name][, options][, fn])#
History
| Version | Changes |
|---|---|
| v18.17.0 | Added the |
| v18.8.0 | Add a |
| v18.7.0 | Add a |
| v18.0.0 | Added in: v18.0.0 |
name<string> The name of the test, which is displayed when reporting testresults.Default: Thenameproperty offn, or'<anonymous>'iffndoes not have a name.options<Object> Configuration options for the test. The followingproperties are supported:concurrency<number> |<boolean> If a number is provided,then that many tests would run in parallel within the application thread.Iftrue, all scheduled asynchronous tests run concurrently within thethread. Iffalse, only one test runs at a time.If unspecified, subtests inherit this value from their parent.Default:false.only<boolean> If truthy, and the test context is configured to runonlytests, then this test will be run. Otherwise, the test is skipped.Default:false.signal<AbortSignal> Allows aborting an in-progress test.skip<boolean> |<string> If truthy, the test is skipped. If a string isprovided, that string is displayed in the test results as the reason forskipping the test.Default:false.todo<boolean> |<string> If truthy, the test marked asTODO. If a stringis provided, that string is displayed in the test results as the reason whythe test isTODO.Default:false.timeout<number> A number of milliseconds the test will fail after.If unspecified, subtests inherit this value from their parent.Default:Infinity.
fn<Function> |<AsyncFunction> The function under test. The first argumentto this function is aTestContextobject. If the test uses callbacks,the callback function is passed as the second argument.Default: A no-opfunction.- Returns:<Promise> Resolved with
undefinedoncethe test completes, or immediately if the test runs withindescribe().
Thetest() function is the value imported from thetest module. Eachinvocation of this function results in reporting the test to the<TestsStream>.
TheTestContext object passed to thefn argument can be used to performactions related to the current test. Examples include skipping the test, addingadditional diagnostic information, or creating subtests.
test() returns aPromise that resolves once the test completes.iftest() is called within adescribe() block, it resolve immediately.The return value can usually be discarded for top level tests.However, the return value from subtests should be used to prevent the parenttest from finishing first and cancelling the subtestas shown in the following example.
test('top level test',async (t) => {// The setTimeout() in the following subtest would cause it to outlive its// parent test if 'await' is removed on the next line. Once the parent test// completes, it will cancel any outstanding subtests.await t.test('longer running subtest',async (t) => {returnnewPromise((resolve, reject) => {setTimeout(resolve,1000); }); });});Thetimeout option can be used to fail the test if it takes longer thantimeout milliseconds to complete. However, it is not a reliable mechanism forcanceling tests because a running test might block the application thread andthus prevent the scheduled cancellation.
test.skip([name][, options][, fn])#
Shorthand for skipping a test,same astest([name], { skip: true }[, fn]).
test.todo([name][, options][, fn])#
Shorthand for marking a test asTODO,same astest([name], { todo: true }[, fn]).
test.only([name][, options][, fn])#
Shorthand for marking a test asonly,same astest([name], { only: true }[, fn]).
describe([name][, options][, fn])#
name<string> The name of the suite, which is displayed when reporting testresults.Default: Thenameproperty offn, or'<anonymous>'iffndoes not have a name.options<Object> Configuration options for the suite.supports the same options astest([name][, options][, fn]).fn<Function> |<AsyncFunction> The function under suitedeclaring all subtests and subsuites.The first argument to this function is aSuiteContextobject.Default: A no-op function.- Returns:<Promise> Immediately fulfilled with
undefined.
Thedescribe() function imported from thenode:test module. Eachinvocation of this function results in the creation of a Subtest.After invocation of top leveldescribe functions,all top level tests and suites will execute.
describe.skip([name][, options][, fn])#
Shorthand for skipping a suite, same asdescribe([name], { skip: true }[, fn]).
describe.todo([name][, options][, fn])#
Shorthand for marking a suite asTODO, same asdescribe([name], { todo: true }[, fn]).
describe.only([name][, options][, fn])#
Shorthand for marking a suite asonly, same asdescribe([name], { only: true }[, fn]).
it([name][, options][, fn])#
History
| Version | Changes |
|---|---|
| v18.16.0 | Calling |
| v18.6.0, v16.17.0 | Added in: v18.6.0, v16.17.0 |
Shorthand fortest().
Theit() function is imported from thenode:test module.
it.skip([name][, options][, fn])#
Shorthand for skipping a test,same asit([name], { skip: true }[, fn]).
it.todo([name][, options][, fn])#
Shorthand for marking a test asTODO,same asit([name], { todo: true }[, fn]).
it.only([name][, options][, fn])#
Shorthand for marking a test asonly,same asit([name], { only: true }[, fn]).
before([fn][, options])#
fn<Function> |<AsyncFunction> The hook function.If the hook uses callbacks,the callback function is passed as the second argument.Default: A no-opfunction.options<Object> Configuration options for the hook. The followingproperties are supported:signal<AbortSignal> Allows aborting an in-progress hook.timeout<number> A number of milliseconds the hook will fail after.If unspecified, subtests inherit this value from their parent.Default:Infinity.
This function is used to create a hook running before running a suite.
describe('tests',async () => {before(() =>console.log('about to run some test'));it('is a subtest',() => { assert.ok('some relevant assertion here'); });});after([fn][, options])#
fn<Function> |<AsyncFunction> The hook function.If the hook uses callbacks,the callback function is passed as the second argument.Default: A no-opfunction.options<Object> Configuration options for the hook. The followingproperties are supported:signal<AbortSignal> Allows aborting an in-progress hook.timeout<number> A number of milliseconds the hook will fail after.If unspecified, subtests inherit this value from their parent.Default:Infinity.
This function is used to create a hook running after running a suite.
describe('tests',async () => {after(() =>console.log('finished running tests'));it('is a subtest',() => { assert.ok('some relevant assertion here'); });});beforeEach([fn][, options])#
fn<Function> |<AsyncFunction> The hook function.If the hook uses callbacks,the callback function is passed as the second argument.Default: A no-opfunction.options<Object> Configuration options for the hook. The followingproperties are supported:signal<AbortSignal> Allows aborting an in-progress hook.timeout<number> A number of milliseconds the hook will fail after.If unspecified, subtests inherit this value from their parent.Default:Infinity.
This function is used to create a hook runningbefore each subtest of the current suite.
describe('tests',async () => {beforeEach(() =>console.log('about to run a test'));it('is a subtest',() => { assert.ok('some relevant assertion here'); });});afterEach([fn][, options])#
fn<Function> |<AsyncFunction> The hook function.If the hook uses callbacks,the callback function is passed as the second argument.Default: A no-opfunction.options<Object> Configuration options for the hook. The followingproperties are supported:signal<AbortSignal> Allows aborting an in-progress hook.timeout<number> A number of milliseconds the hook will fail after.If unspecified, subtests inherit this value from their parent.Default:Infinity.
This function is used to create a hook runningafter each subtest of the current test.
describe('tests',async () => {afterEach(() =>console.log('finished running a test'));it('is a subtest',() => { assert.ok('some relevant assertion here'); });});Class:MockFunctionContext#
TheMockFunctionContext class is used to inspect or manipulate the behavior ofmocks created via theMockTracker APIs.
ctx.calls#
A getter that returns a copy of the internal array used to track calls to themock. Each entry in the array is an object with the following properties.
arguments<Array> An array of the arguments passed to the mock function.error<any> If the mocked function threw then this property contains thethrown value.Default:undefined.result<any> The value returned by the mocked function.stack<Error> AnErrorobject whose stack can be used to determine thecallsite of the mocked function invocation.target<Function> |<undefined> If the mocked function is a constructor, thisfield contains the class being constructed. Otherwise this will beundefined.this<any> The mocked function'sthisvalue.
ctx.callCount()#
- Returns:<integer> The number of times that this mock has been invoked.
This function returns the number of times that this mock has been invoked. Thisfunction is more efficient than checkingctx.calls.length becausectx.callsis a getter that creates a copy of the internal call tracking array.
ctx.mockImplementation(implementation)#
implementation<Function> |<AsyncFunction> The function to be used as themock's new implementation.
This function is used to change the behavior of an existing mock.
The following example creates a mock function usingt.mock.fn(), calls themock function, and then changes the mock implementation to a different function.
test('changes a mock behavior',(t) => {let cnt =0;functionaddOne() { cnt++;return cnt; }functionaddTwo() { cnt +=2;return cnt; }const fn = t.mock.fn(addOne); assert.strictEqual(fn(),1); fn.mock.mockImplementation(addTwo); assert.strictEqual(fn(),3); assert.strictEqual(fn(),5);});ctx.mockImplementationOnce(implementation[, onCall])#
implementation<Function> |<AsyncFunction> The function to be used as themock's implementation for the invocation number specified byonCall.onCall<integer> The invocation number that will useimplementation. Ifthe specified invocation has already occurred then an exception is thrown.Default: The number of the next invocation.
This function is used to change the behavior of an existing mock for a singleinvocation. Once invocationonCall has occurred, the mock will revert towhatever behavior it would have used hadmockImplementationOnce() not beencalled.
The following example creates a mock function usingt.mock.fn(), calls themock function, changes the mock implementation to a different function for thenext invocation, and then resumes its previous behavior.
test('changes a mock behavior once',(t) => {let cnt =0;functionaddOne() { cnt++;return cnt; }functionaddTwo() { cnt +=2;return cnt; }const fn = t.mock.fn(addOne); assert.strictEqual(fn(),1); fn.mock.mockImplementationOnce(addTwo); assert.strictEqual(fn(),3); assert.strictEqual(fn(),4);});ctx.resetCalls()#
Resets the call history of the mock function.
ctx.restore()#
Resets the implementation of the mock function to its original behavior. Themock can still be used after calling this function.
Class:MockTracker#
TheMockTracker class is used to manage mocking functionality. The test runnermodule provides a top levelmock export which is aMockTracker instance.Each test also provides its ownMockTracker instance via the test context'smock property.
mock.fn([original[, implementation]][, options])#
original<Function> |<AsyncFunction> An optional function to create a mock on.Default: A no-op function.implementation<Function> |<AsyncFunction> An optional function used as themock implementation fororiginal. This is useful for creating mocks thatexhibit one behavior for a specified number of calls and then restore thebehavior oforiginal.Default: The function specified byoriginal.options<Object> Optional configuration options for the mock function. Thefollowing properties are supported:times<integer> The number of times that the mock will use the behavior ofimplementation. Once the mock function has been calledtimestimes, itwill automatically restore the behavior oforiginal. This value must be aninteger greater than zero.Default:Infinity.
- Returns:<Proxy> The mocked function. The mocked function contains a special
mockproperty, which is an instance ofMockFunctionContext, and canbe used for inspecting and changing the behavior of the mocked function.
This function is used to create a mock function.
The following example creates a mock function that increments a counter by oneon each invocation. Thetimes option is used to modify the mock behavior suchthat the first two invocations add two to the counter instead of one.
test('mocks a counting function',(t) => {let cnt =0;functionaddOne() { cnt++;return cnt; }functionaddTwo() { cnt +=2;return cnt; }const fn = t.mock.fn(addOne, addTwo, {times:2 }); assert.strictEqual(fn(),2); assert.strictEqual(fn(),4); assert.strictEqual(fn(),5); assert.strictEqual(fn(),6);});mock.getter(object, methodName[, implementation][, options])#
This function is syntax sugar forMockTracker.method withoptions.getterset totrue.
mock.method(object, methodName[, implementation][, options])#
object<Object> The object whose method is being mocked.methodName<string> |<symbol> The identifier of the method onobjectto mock.Ifobject[methodName]is not a function, an error is thrown.implementation<Function> |<AsyncFunction> An optional function used as themock implementation forobject[methodName].Default: The original methodspecified byobject[methodName].options<Object> Optional configuration options for the mock method. Thefollowing properties are supported:getter<boolean> Iftrue,object[methodName]is treated as a getter.This option cannot be used with thesetteroption.Default: false.setter<boolean> Iftrue,object[methodName]is treated as a setter.This option cannot be used with thegetteroption.Default: false.times<integer> The number of times that the mock will use the behavior ofimplementation. Once the mocked method has been calledtimestimes, itwill automatically restore the original behavior. This value must be aninteger greater than zero.Default:Infinity.
- Returns:<Proxy> The mocked method. The mocked method contains a special
mockproperty, which is an instance ofMockFunctionContext, and canbe used for inspecting and changing the behavior of the mocked method.
This function is used to create a mock on an existing object method. Thefollowing example demonstrates how a mock is created on an existing objectmethod.
test('spies on an object method',(t) => {const number = {value:5,subtract(a) {returnthis.value - a; }, }; t.mock.method(number,'subtract'); assert.strictEqual(number.subtract.mock.calls.length,0); assert.strictEqual(number.subtract(3),2); assert.strictEqual(number.subtract.mock.calls.length,1);const call = number.subtract.mock.calls[0]; assert.deepStrictEqual(call.arguments, [3]); assert.strictEqual(call.result,2); assert.strictEqual(call.error,undefined); assert.strictEqual(call.target,undefined); assert.strictEqual(call.this, number);});mock.reset()#
This function restores the default behavior of all mocks that were previouslycreated by thisMockTracker and disassociates the mocks from theMockTracker instance. Once disassociated, the mocks can still be used, but theMockTracker instance can no longer be used to reset their behavior orotherwise interact with them.
After each test completes, this function is called on the test context'sMockTracker. If the globalMockTracker is used extensively, calling thisfunction manually is recommended.
mock.restoreAll()#
This function restores the default behavior of all mocks that were previouslycreated by thisMockTracker. Unlikemock.reset(),mock.restoreAll() doesnot disassociate the mocks from theMockTracker instance.
mock.setter(object, methodName[, implementation][, options])#
This function is syntax sugar forMockTracker.method withoptions.setterset totrue.
Class:MockTimers#
Mocking timers is a technique commonly used in software testing to simulate andcontrol the behavior of timers, such assetInterval andsetTimeout,without actually waiting for the specified time intervals.
TheMockTracker provides a top-leveltimers exportwhich is aMockTimers instance.
timers.enable([timers])#
Enables timer mocking for the specified timers.
timers<Array> An optional array containing the timers to mock.The currently supported timer values are'setInterval','setTimeout',and'setImmediate'. If no value is provided, all timers ('setInterval','clearInterval','setTimeout','clearTimeout','setImmediate',and'clearImmediate') will be mocked by default.
Note: When you enable mocking for a specific timer, its associatedclear function will also be implicitly mocked.
Example usage:
import { mock }from'node:test';mock.timers.enable(['setInterval']);const { mock } =require('node:test');mock.timers.enable(['setInterval']);
The above example enables mocking for thesetInterval timer andimplicitly mocks theclearInterval function. Only thesetIntervalandclearInterval functions fromnode:timers,node:timers/promises, andglobalThis will be mocked.
Alternatively, if you callmock.timers.enable() without any parameters:
All timers ('setInterval','clearInterval','setTimeout', and'clearTimeout')will be mocked. ThesetInterval,clearInterval,setTimeout, andclearTimeoutfunctions fromnode:timers,node:timers/promises,andglobalThis will be mocked.
timers.reset()#
This function restores the default behavior of all mocks that were previouslycreated by thisMockTimers instance and disassociates the mocksfrom theMockTracker instance.
Note: After each test completes, this function is called onthe test context'sMockTracker.
import { mock }from'node:test';mock.timers.reset();const { mock } =require('node:test');mock.timers.reset();
timers[Symbol.dispose]()#
Callstimers.reset().
timers.tick(milliseconds)#
Advances time for all mocked timers.
milliseconds<number> The amount of time, in milliseconds,to advance the timers.
Note: This diverges from howsetTimeout in Node.js behaves and acceptsonly positive numbers. In Node.js,setTimeout with negative numbers isonly supported for web compatibility reasons.
The following example mocks asetTimeout function andby using.tick advances intime triggering all pending timers.
import assertfrom'node:assert';import { test }from'node:test';test('mocks setTimeout to be executed synchronously without having to actually wait for it',(context) => {const fn = context.mock.fn(); context.mock.timers.enable(['setTimeout']);setTimeout(fn,9999); assert.strictEqual(fn.mock.callCount(),0);// Advance in time context.mock.timers.tick(9999); assert.strictEqual(fn.mock.callCount(),1);});const assert =require('node:assert');const { test } =require('node:test');test('mocks setTimeout to be executed synchronously without having to actually wait for it',(context) => {const fn = context.mock.fn(); context.mock.timers.enable(['setTimeout']);setTimeout(fn,9999); assert.strictEqual(fn.mock.callCount(),0);// Advance in time context.mock.timers.tick(9999); assert.strictEqual(fn.mock.callCount(),1);});
Alternativelly, the.tick function can be called many times
import assertfrom'node:assert';import { test }from'node:test';test('mocks setTimeout to be executed synchronously without having to actually wait for it',(context) => {const fn = context.mock.fn(); context.mock.timers.enable(['setTimeout']);const nineSecs =9000;setTimeout(fn, nineSecs);const twoSeconds =3000; context.mock.timers.tick(twoSeconds); context.mock.timers.tick(twoSeconds); context.mock.timers.tick(twoSeconds); assert.strictEqual(fn.mock.callCount(),1);});const assert =require('node:assert');const { test } =require('node:test');test('mocks setTimeout to be executed synchronously without having to actually wait for it',(context) => {const fn = context.mock.fn(); context.mock.timers.enable(['setTimeout']);const nineSecs =9000;setTimeout(fn, nineSecs);const twoSeconds =3000; context.mock.timers.tick(twoSeconds); context.mock.timers.tick(twoSeconds); context.mock.timers.tick(twoSeconds); assert.strictEqual(fn.mock.callCount(),1);});
Using clear functions#
As mentioned, all clear functions from timers (clearTimeout andclearInterval)are implicity mocked. Take a look at this example usingsetTimeout:
import assertfrom'node:assert';import { test }from'node:test';test('mocks setTimeout to be executed synchronously without having to actually wait for it',(context) => {const fn = context.mock.fn();// Optionally choose what to mock context.mock.timers.enable(['setTimeout']);const id =setTimeout(fn,9999);// Implicity mocked as wellclearTimeout(id); context.mock.timers.tick(9999);// As that setTimeout was cleared the mock function will never be called assert.strictEqual(fn.mock.callCount(),0);});const assert =require('node:assert');const { test } =require('node:test');test('mocks setTimeout to be executed synchronously without having to actually wait for it',(context) => {const fn = context.mock.fn();// Optionally choose what to mock context.mock.timers.enable(['setTimeout']);const id =setTimeout(fn,9999);// Implicity mocked as wellclearTimeout(id); context.mock.timers.tick(9999);// As that setTimeout was cleared the mock function will never be called assert.strictEqual(fn.mock.callCount(),0);});
Working with Node.js timers modules#
Once you enable mocking timers,node:timers,node:timers/promises modules,and timers from the Node.js global context are enabled:
Note: Destructuring functions such asimport { setTimeout } from 'node:timers' is currentlynot supported by this API.
import assertfrom'node:assert';import { test }from'node:test';import nodeTimersfrom'node:timers';import nodeTimersPromisesfrom'node:timers/promises';test('mocks setTimeout to be executed synchronously without having to actually wait for it',async (context) => {const globalTimeoutObjectSpy = context.mock.fn();const nodeTimerSpy = context.mock.fn();const nodeTimerPromiseSpy = context.mock.fn();// Optionally choose what to mock context.mock.timers.enable(['setTimeout']);setTimeout(globalTimeoutObjectSpy,9999); nodeTimers.setTimeout(nodeTimerSpy,9999);const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy);// Advance in time context.mock.timers.tick(9999); assert.strictEqual(globalTimeoutObjectSpy.mock.callCount(),1); assert.strictEqual(nodeTimerSpy.mock.callCount(),1);await promise; assert.strictEqual(nodeTimerPromiseSpy.mock.callCount(),1);});const assert =require('node:assert');const { test } =require('node:test');const nodeTimers =require('node:timers');const nodeTimersPromises =require('node:timers/promises');test('mocks setTimeout to be executed synchronously without having to actually wait for it',async (context) => {const globalTimeoutObjectSpy = context.mock.fn();const nodeTimerSpy = context.mock.fn();const nodeTimerPromiseSpy = context.mock.fn();// Optionally choose what to mock context.mock.timers.enable(['setTimeout']);setTimeout(globalTimeoutObjectSpy,9999); nodeTimers.setTimeout(nodeTimerSpy,9999);const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy);// Advance in time context.mock.timers.tick(9999); assert.strictEqual(globalTimeoutObjectSpy.mock.callCount(),1); assert.strictEqual(nodeTimerSpy.mock.callCount(),1);await promise; assert.strictEqual(nodeTimerPromiseSpy.mock.callCount(),1);});
In Node.js,setInterval fromnode:timers/promisesis anAsyncGenerator and is also supported by this API:
import assertfrom'node:assert';import { test }from'node:test';import nodeTimersPromisesfrom'node:timers/promises';test('should tick five times testing a real use case',async (context) => { context.mock.timers.enable(['setInterval']);const expectedIterations =3;const interval =1000;const startedAt =Date.now();asyncfunctionrun() {const times = [];forawait (const timeof nodeTimersPromises.setInterval(interval, startedAt)) { times.push(time);if (times.length === expectedIterations)break; }return times; }const r =run(); context.mock.timers.tick(interval); context.mock.timers.tick(interval); context.mock.timers.tick(interval);const timeResults =await r; assert.strictEqual(timeResults.length, expectedIterations);for (let it =1; it < expectedIterations; it++) { assert.strictEqual(timeResults[it -1], startedAt + (interval * it)); }});const assert =require('node:assert');const { test } =require('node:test');const nodeTimersPromises =require('node:timers/promises');test('should tick five times testing a real use case',async (context) => { context.mock.timers.enable(['setInterval']);const expectedIterations =3;const interval =1000;const startedAt =Date.now();asyncfunctionrun() {const times = [];forawait (const timeof nodeTimersPromises.setInterval(interval, startedAt)) { times.push(time);if (times.length === expectedIterations)break; }return times; }const r =run(); context.mock.timers.tick(interval); context.mock.timers.tick(interval); context.mock.timers.tick(interval);const timeResults =await r; assert.strictEqual(timeResults.length, expectedIterations);for (let it =1; it < expectedIterations; it++) { assert.strictEqual(timeResults[it -1], startedAt + (interval * it)); }});
timers.runAll()#
Triggers all pending mocked timers immediately.
The example below triggers all pending timers immediately,causing them to execute without any delay.
import assertfrom'node:assert';import { test }from'node:test';test('runAll functions following the given order',(context) => { context.mock.timers.enable(['setTimeout']);const results = [];setTimeout(() => results.push(1),9999);// Notice that if both timers have the same timeout,// the order of execution is guaranteedsetTimeout(() => results.push(3),8888);setTimeout(() => results.push(2),8888); assert.deepStrictEqual(results, []); context.mock.timers.runAll(); assert.deepStrictEqual(results, [3,2,1]);});const assert =require('node:assert');const { test } =require('node:test');test('runAll functions following the given order',(context) => { context.mock.timers.enable(['setTimeout']);const results = [];setTimeout(() => results.push(1),9999);// Notice that if both timers have the same timeout,// the order of execution is guaranteedsetTimeout(() => results.push(3),8888);setTimeout(() => results.push(2),8888); assert.deepStrictEqual(results, []); context.mock.timers.runAll(); assert.deepStrictEqual(results, [3,2,1]);});
Note: TherunAll() function is specifically designed fortriggering timers in the context of timer mocking.It does not have any effect on real-time systemclocks or actual timers outside of the mocking environment.
Class:TestsStream#
History
| Version | Changes |
|---|---|
| v18.17.0 | added type to test:pass and test:fail events for when the test is a suite. |
| v18.9.0, v16.19.0 | Added in: v18.9.0, v16.19.0 |
- Extends<ReadableStream>
A successful call torun() method will return a new<TestsStream>object, streaming a series of events representing the execution of the tests.TestsStream will emit events, in the order of the tests definition
Event:'test:coverage'#
data<Object>summary<Object> An object containing the coverage report.files<Array> An array of coverage reports for individual files. Eachreport is an object with the following schema:path<string> The absolute path of the file.totalLineCount<number> The total number of lines.totalBranchCount<number> The total number of branches.totalFunctionCount<number> The total number of functions.coveredLineCount<number> The number of covered lines.coveredBranchCount<number> The number of covered branches.coveredFunctionCount<number> The number of covered functions.coveredLinePercent<number> The percentage of lines covered.coveredBranchPercent<number> The percentage of branches covered.coveredFunctionPercent<number> The percentage of functions covered.uncoveredLineNumbers<Array> An array of integers representing linenumbers that are uncovered.
totals<Object> An object containing a summary of coverage for allfiles.totalLineCount<number> The total number of lines.totalBranchCount<number> The total number of branches.totalFunctionCount<number> The total number of functions.coveredLineCount<number> The number of covered lines.coveredBranchCount<number> The number of covered branches.coveredFunctionCount<number> The number of covered functions.coveredLinePercent<number> The percentage of lines covered.coveredBranchPercent<number> The percentage of branches covered.coveredFunctionPercent<number> The percentage of functions covered.
workingDirectory<string> The working directory when code coveragebegan. This is useful for displaying relative path names in case the testschanged the working directory of the Node.js process.
nesting<number> The nesting level of the test.
Emitted when code coverage is enabled and all tests have completed.
Event:'test:dequeue'#
data<Object>column<number> |<undefined> The column number where the test is defined, orundefinedif the test was run through the REPL.file<string> |<undefined> The path of the test file,undefinedif test was run through the REPL.line<number> |<undefined> The line number where the test is defined, orundefinedif the test was run through the REPL.name<string> The test name.nesting<number> The nesting level of the test.
Emitted when a test is dequeued, right before it is executed.
Event:'test:diagnostic'#
data<Object>column<number> |<undefined> The column number where the test is defined, orundefinedif the test was run through the REPL.file<string> |<undefined> The path of the test file,undefinedif test was run through the REPL.line<number> |<undefined> The line number where the test is defined, orundefinedif the test was run through the REPL.message<string> The diagnostic message.nesting<number> The nesting level of the test.
Emitted whencontext.diagnostic is called.
Event:'test:enqueue'#
data<Object>column<number> |<undefined> The column number where the test is defined, orundefinedif the test was run through the REPL.file<string> |<undefined> The path of the test file,undefinedif test was run through the REPL.line<number> |<undefined> The line number where the test is defined, orundefinedif the test was run through the REPL.name<string> The test name.nesting<number> The nesting level of the test.
Emitted when a test is enqueued for execution.
Event:'test:fail'#
data<Object>column<number> |<undefined> The column number where the test is defined, orundefinedif the test was run through the REPL.details<Object> Additional execution metadata.duration_ms<number> The duration of the test in milliseconds.error<Error> An error wrapping the error thrown by the test.cause<Error> The actual error thrown by the test.
type<string> |<undefined> The type of the test, used to denote whetherthis is a suite.
file<string> |<undefined> The path of the test file,undefinedif test was run through the REPL.line<number> |<undefined> The line number where the test is defined, orundefinedif the test was run through the REPL.name<string> The test name.nesting<number> The nesting level of the test.testNumber<number> The ordinal number of the test.todo<string> |<boolean> |<undefined> Present ifcontext.todois calledskip<string> |<boolean> |<undefined> Present ifcontext.skipis called
Emitted when a test fails.
Event:'test:pass'#
data<Object>column<number> |<undefined> The column number where the test is defined, orundefinedif the test was run through the REPL.details<Object> Additional execution metadata.duration_ms<number> The duration of the test in milliseconds.type<string> |<undefined> The type of the test, used to denote whetherthis is a suite.
file<string> |<undefined> The path of the test file,undefinedif test was run through the REPL.line<number> |<undefined> The line number where the test is defined, orundefinedif the test was run through the REPL.name<string> The test name.nesting<number> The nesting level of the test.testNumber<number> The ordinal number of the test.todo<string> |<boolean> |<undefined> Present ifcontext.todois calledskip<string> |<boolean> |<undefined> Present ifcontext.skipis called
Emitted when a test passes.
Event:'test:plan'#
data<Object>column<number> |<undefined> The column number where the test is defined, orundefinedif the test was run through the REPL.file<string> |<undefined> The path of the test file,undefinedif test was run through the REPL.line<number> |<undefined> The line number where the test is defined, orundefinedif the test was run through the REPL.nesting<number> The nesting level of the test.count<number> The number of subtests that have ran.
Emitted when all subtests have completed for a given test.
Event:'test:start'#
data<Object>column<number> |<undefined> The column number where the test is defined, orundefinedif the test was run through the REPL.file<string> |<undefined> The path of the test file,undefinedif test was run through the REPL.line<number> |<undefined> The line number where the test is defined, orundefinedif the test was run through the REPL.name<string> The test name.nesting<number> The nesting level of the test.
Emitted when a test starts reporting its own and its subtests status.This event is guaranteed to be emitted in the same order as the tests aredefined.
Event:'test:stderr'#
data<Object>column<number> |<undefined> The column number where the test is defined, orundefinedif the test was run through the REPL.file<string> The path of the test file.line<number> |<undefined> The line number where the test is defined, orundefinedif the test was run through the REPL.message<string> The message written tostderr.
Emitted when a running test writes tostderr.This event is only emitted if--test flag is passed.
Event:'test:stdout'#
data<Object>column<number> |<undefined> The column number where the test is defined, orundefinedif the test was run through the REPL.file<string> The path of the test file.line<number> |<undefined> The line number where the test is defined, orundefinedif the test was run through the REPL.message<string> The message written tostdout.
Emitted when a running test writes tostdout.This event is only emitted if--test flag is passed.
Event:'test:watch:drained'#
Emitted when no more tests are queued for execution in watch mode.
Class:TestContext#
History
| Version | Changes |
|---|---|
| v18.17.0 | The |
| v18.0.0 | Added in: v18.0.0 |
An instance ofTestContext is passed to each test function in order tointeract with the test runner. However, theTestContext constructor is notexposed as part of the API.
context.before([fn][, options])#
fn<Function> |<AsyncFunction> The hook function. The first argumentto this function is aTestContextobject. If the hook uses callbacks,the callback function is passed as the second argument.Default: A no-opfunction.options<Object> Configuration options for the hook. The followingproperties are supported:signal<AbortSignal> Allows aborting an in-progress hook.timeout<number> A number of milliseconds the hook will fail after.If unspecified, subtests inherit this value from their parent.Default:Infinity.
This function is used to create a hook running beforesubtest of the current test.
context.beforeEach([fn][, options])#
fn<Function> |<AsyncFunction> The hook function. The first argumentto this function is aTestContextobject. If the hook uses callbacks,the callback function is passed as the second argument.Default: A no-opfunction.options<Object> Configuration options for the hook. The followingproperties are supported:signal<AbortSignal> Allows aborting an in-progress hook.timeout<number> A number of milliseconds the hook will fail after.If unspecified, subtests inherit this value from their parent.Default:Infinity.
This function is used to create a hook runningbefore 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) => { assert.ok('some relevant assertion here'); }, );});context.after([fn][, options])#
fn<Function> |<AsyncFunction> The hook function. The first argumentto this function is aTestContextobject. If the hook uses callbacks,the callback function is passed as the second argument.Default: A no-opfunction.options<Object> Configuration options for the hook. The followingproperties are supported:signal<AbortSignal> Allows aborting an in-progress hook.timeout<number> A number of milliseconds the hook will fail after.If unspecified, subtests inherit this value from their parent.Default:Infinity.
This function is used to create a hook that runs after the current testfinishes.
test('top level test',async (t) => { t.after((t) => t.diagnostic(`finished running${t.name}`)); assert.ok('some relevant assertion here');});context.afterEach([fn][, options])#
fn<Function> |<AsyncFunction> The hook function. The first argumentto this function is aTestContextobject. If the hook uses callbacks,the callback function is passed as the second argument.Default: A no-opfunction.options<Object> Configuration options for the hook. The followingproperties are supported:signal<AbortSignal> Allows aborting an in-progress hook.timeout<number> A number of milliseconds the hook will fail after.If unspecified, subtests inherit this value from their parent.Default:Infinity.
This function is used to create a hook runningafter 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) => { assert.ok('some relevant assertion here'); }, );});context.diagnostic(message)#
message<string> Message to be reported.
This function is used to write diagnostics to the output. Any diagnosticinformation is included at the end of the test's results. This function doesnot return a value.
test('top level test',(t) => { t.diagnostic('A diagnostic message');});context.name#
The name of the test.
context.runOnly(shouldRunOnlyTests)#
shouldRunOnlyTests<boolean> Whether or not to runonlytests.
IfshouldRunOnlyTests is truthy, the test context will only run tests thathave theonly option set. Otherwise, all tests are run. If Node.js was notstarted with the--test-only command-line option, this function is ano-op.
test('top level test',(t) => {// The test context can be set to run subtests with the 'only' option. t.runOnly(true);returnPromise.all([ t.test('this subtest is now skipped'), t.test('this subtest is run', {only:true }), ]);});context.signal#
- <AbortSignal> Can be used to abort test subtasks when the test has beenaborted.
test('top level test',async (t) => {awaitfetch('some/uri', {signal: t.signal });});context.skip([message])#
message<string> Optional skip message.
This function causes the test's output to indicate the test as skipped. Ifmessage is provided, it is included in the output. Callingskip() doesnot terminate execution of the test function. This function does not return avalue.
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])#
message<string> OptionalTODOmessage.
This function adds aTODO directive to the test's output. Ifmessage isprovided, it is included in the output. Callingtodo() does not terminateexecution 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([name][, options][, fn])#
History
| Version | Changes |
|---|---|
| v18.8.0 | Add a |
| v18.7.0 | Add a |
| v18.0.0 | Added in: v18.0.0 |
name<string> The name of the subtest, which is displayed when reportingtest results.Default: Thenameproperty offn, or'<anonymous>'iffndoes not have a name.options<Object> Configuration options for the subtest. The followingproperties are supported:concurrency<number> |<boolean> |<null> If a number is provided,then that many tests would run in parallel within the application thread.Iftrue, it would run all subtests in parallel.Iffalse, it would only run one test at a time.If unspecified, subtests inherit this value from their parent.Default:null.only<boolean> If truthy, and the test context is configured to runonlytests, then this test will be run. Otherwise, the test is skipped.Default:false.signal<AbortSignal> Allows aborting an in-progress test.skip<boolean> |<string> If truthy, the test is skipped. If a string isprovided, that string is displayed in the test results as the reason forskipping the test.Default:false.todo<boolean> |<string> If truthy, the test marked asTODO. If a stringis provided, that string is displayed in the test results as the reason whythe test isTODO.Default:false.timeout<number> A number of milliseconds the test will fail after.If unspecified, subtests inherit this value from their parent.Default:Infinity.
fn<Function> |<AsyncFunction> The function under test. The first argumentto this function is aTestContextobject. If the test uses callbacks,the callback function is passed as the second argument.Default: A no-opfunction.- Returns:<Promise> Resolved with
undefinedonce the test completes.
This function is used to create subtests under the current test. This functionbehaves in the same fashion as the top leveltest() function.
test('top level test',async (t) => {await t.test('This is a subtest', {only:false,skip:false,concurrency:1,todo:false },(t) => { assert.ok('some relevant assertion here'); }, );});Class:SuiteContext#
An instance ofSuiteContext is passed to each suite function in order tointeract with the test runner. However, theSuiteContext constructor is notexposed as part of the API.
context.name#
The name of the suite.
context.signal#
- <AbortSignal> Can be used to abort test subtasks when the test has beenaborted.