- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
Node.js v22.11.0 文档
- Node.js v22.11.0
-
目录
- 测试运行器
- 子测试
- 跳过测试
- TODO 测试
describe()
和it()
别名only
测试- 按名称过滤测试
- 无关的异步活动
- 监视模式
- 从命令行运行测试
- 收集代码覆盖率
- 模拟
- 快照测试
- 测试报告器
run([options])
suite([name][, options][, fn])
suite.skip([name][, options][, fn])
suite.todo([name][, options][, fn])
suite.only([name][, options][, fn])
test([name][, options][, fn])
test.skip([name][, options][, fn])
test.todo([name][, options][, fn])
test.only([name][, options][, fn])
describe([name][, options][, fn])
describe.skip([name][, options][, fn])
describe.todo([name][, options][, fn])
describe.only([name][, options][, fn])
it([name][, options][, fn])
it.skip([name][, options][, fn])
it.todo([name][, options][, fn])
it.only([name][, options][, fn])
before([fn][, options])
after([fn][, options])
beforeEach([fn][, options])
afterEach([fn][, options])
snapshot
- 类:
MockFunctionContext
- 类:
MockModuleContext
- 类:
MockTracker
- 类:
MockTimers
- 类:
TestsStream
- 类:
TestContext
context.before([fn][, options])
context.beforeEach([fn][, options])
context.after([fn][, options])
context.afterEach([fn][, options])
context.assert
context.diagnostic(message)
context.filePath
context.fullName
context.name
context.plan(count)
context.runOnly(shouldRunOnlyTests)
context.signal
context.skip([message])
context.todo([message])
context.test([name][, options][, fn])
- 类:
SuiteContext
- 测试运行器
-
导航
- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
- 其他版本
测试运行器#
¥Test runner
¥Stability: 2 - Stable
源代码: lib/test.js
node:test
模块有助于创建 JavaScript 测试。要访问它:
¥The node:test
module facilitates the creation of JavaScript tests.
To access it:
import test from 'node:test';
const test = require('node:test');
此模块仅在 node:
协议下可用。以下将不起作用:
¥This module is only available under the node:
scheme. The following will not
work:
import test from 'test';
const test = require('test');
通过 test
模块创建的测试由单个函数组成,该函数以三种方式之一进行处理:
¥Tests created via the test
module consist of a single function that is
processed in one of three ways:
-
同步的函数,如果抛出异常则认为失败,否则认为通过。
¥A synchronous function that is considered failing if it throws an exception, and is considered passing otherwise.
-
返回
Promise
的函数,如果Promise
拒绝,则视为失败;如果Promise
满足,则视为通过。¥A function that returns a
Promise
that is considered failing if thePromise
rejects, and is considered passing if thePromise
fulfills. -
接收回调函数的函数。如果回调接收到任何真值作为其第一个参数,则认为测试失败。如果非真值作为第一个参数传给回调,则认为测试通过。如果测试函数接收到回调函数并且还返回
Promise
,则测试将失败。¥A function that receives a callback function. If the callback receives any truthy value as its first argument, the test is considered failing. If a falsy value is passed as the first argument to the callback, the test is considered passing. If the test function receives a callback function and also returns a
Promise
, the test will fail.
以下示例说明了如何使用 test
模块编写测试。
¥The following example illustrates how tests are written using the
test
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 settled and 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.
return new Promise((resolve, reject) => {
setImmediate(() => {
reject(new Error('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(new Error('callback failure'));
});
});
如果任何测试失败,则进程退出代码设置为 1
。
¥If any tests fail, the process exit code is set to 1
.
子测试#
¥Subtests
测试上下文的 test()
方法允许创建子测试。它允许你以分层方式构建测试,你可以在更大的测试中创建嵌套测试。此方法的行为与顶层 test()
函数相同。以下示例演示了如何创建具有两个子测试的顶层测试。
¥The test context's test()
method allows subtests to be created.
It allows you to structure your tests in a hierarchical manner,
where you can create nested tests within a larger test.
This method behaves identically to the top level test()
function.
The following example demonstrates 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);
});
});
注意:
beforeEach
和afterEach
钩子在每个子测试执行之间触发。¥Note:
beforeEach
andafterEach
hooks are triggered between each subtest execution.
在本示例中,await
用于确保两个子测试均已完成。这是必要的,因为测试不会等待其子测试完成,这与套件中创建的测试不同。当父测试完成时仍然未完成的任何子测试将被取消并视为失败。任何子测试失败都会导致父测试失败。
¥In this example, await
is used to ensure that both subtests have completed.
This is necessary because tests do not wait for their subtests to
complete, unlike tests created within suites.
Any subtests that are still outstanding when their parent finishes
are cancelled and treated as failures. Any subtest failures cause the parent
test to fail.
跳过测试#
¥Skipping tests
通过将 skip
选项传递给测试,或通过调用测试上下文的 skip()
方法,可以跳过单个测试,如下例所示。
¥Individual tests can be skipped by passing the skip
option to the test, or by
calling the test context's skip()
method as shown in the
following 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');
});
TODO 测试#
¥TODO tests
通过将 todo
选项传递给测试,或通过调用测试上下文的 todo()
方法,可以将单个测试标记为不稳定或不完整,如以下示例所示。这些测试代表需要修复的待实现或错误。TODO 测试会被执行,但不会被视为测试失败,因此不会影响进程退出代码。如果测试被标记为 TODO 并被跳过,则 TODO 选项将被忽略。
¥Individual tests can be marked as flaky or incomplete by passing the todo
option to the test, or by calling the test context's todo()
method, as shown
in the following example. These tests represent a pending implementation or bug
that needs to be fixed. TODO tests are executed, but are not treated as test
failures, and therefore do not affect the process exit code. If a test is marked
as both TODO and skipped, the TODO option is ignored.
// The todo option is used, but no message is provided.
test('todo option', { todo: true }, (t) => {
// This code is executed, but not treated as a failure.
throw new Error('this does not fail the test');
});
// The todo option is used, and a message is provided.
test('todo option with message', { todo: 'this is a todo test' }, (t) => {
// This code is executed.
});
test('todo() method', (t) => {
t.todo();
});
test('todo() method with message', (t) => {
t.todo('this is a todo test and is not treated as a failure');
throw new Error('this does not fail the test');
});
describe()
和 it()
别名#
¥describe()
and it()
aliases
套件和测试也可以使用 describe()
和 it()
函数编写。describe()
是 suite()
的别名,it()
是 test()
的别名。
¥Suites and tests can also be written using the describe()
and it()
functions. describe()
is an alias for suite()
, and it()
is an
alias for test()
.
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()
和 it()
是从 node:test
模块导入的。
¥describe()
and it()
are imported from the node:test
module.
import { describe, it } from 'node:test';
const { describe, it } = require('node:test');
only
测试#
¥only
tests
如果 Node.js 以 --test-only
命令行选项启动,或者禁用测试隔离,则可以通过将 only
选项传递给应运行的测试来跳过除选定子集之外的所有测试。当设置了 only
选项的测试时,所有子测试也会运行。如果套件设置了 only
选项,则将运行该套件中的所有测试,除非它具有设置了 only
选项的后代,在这种情况下,仅运行这些测试。
¥If Node.js is started with the --test-only
command-line option, or test
isolation is disabled, it is possible to skip all tests except for a selected
subset by passing the only
option to the tests that should run. When a test
with the only
option is set, all subtests are also run.
If a suite has the only
option set, all tests within the suite are run,
unless it has descendants with the only
option set, in which case only those
tests are run.
在 test()
/it()
中使用 subtests 时,需要使用 only
选项标记所有祖级测试,以仅运行选定的测试子集。
¥When using subtests within a test()
/it()
, it is required to mark
all ancestor tests with the only
option to run only a
selected subset of tests.
测试上下文的 runOnly()
方法可用于在子测试级别实现相同的行为。未执行的测试将从测试运行器输出中省略。
¥The test context's runOnly()
method can be used to implement the same behavior at the subtest level. Tests
that are not executed are omitted from the test runner output.
// Assume Node.js is run with the --test-only command-line option.
// The suite's 'only' option is set, so these tests are 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.
throw new Error('fail');
});
describe('a suite', () => {
// The 'only' option is set, so this test is run.
it('this test is run', { only: true }, () => {
// This code is run.
});
it('this test is not run', () => {
// This code is not run.
throw new Error('fail');
});
});
describe.only('a suite', () => {
// The 'only' option is set, so this test is run.
it('this test is run', () => {
// This code is run.
});
it('this test is run', () => {
// This code is run.
});
});
按名称过滤测试#
¥Filtering tests by name
--test-name-pattern
命令行选项可用于仅运行名称与提供的模式匹配的测试,而 --test-skip-pattern
选项可用于跳过名称与提供的模式匹配的测试。测试名称模式被解释为 JavaScript 正则表达式。可以多次指定 --test-name-pattern
和 --test-skip-pattern
选项以便运行嵌套测试。对于执行的每个测试,也会运行任何相应的测试钩子,例如 beforeEach()
。未执行的测试将从测试运行器输出中省略。
¥The --test-name-pattern
command-line option can be used to only run
tests whose name matches the provided pattern, and the
--test-skip-pattern
option can be used to skip tests whose name
matches the provided pattern. Test name patterns are interpreted as
JavaScript regular expressions. The --test-name-pattern
and
--test-skip-pattern
options can be specified multiple times in order to run
nested tests. For each test that is executed, any corresponding test hooks,
such as beforeEach()
, are also run. Tests that are not executed are omitted
from the test runner output.
给定以下测试文件,使用 --test-name-pattern="test [1-3]"
选项启动 Node.js 将导致测试运行程序执行 test 1
、test 2
和 test 3
。如果 test 1
不匹配测试名称模式,那么它的子测试将不会执行,尽管匹配模式。同一组测试也可以通过多次传递 --test-name-pattern
来执行(例如 --test-name-pattern="test 1"
、--test-name-pattern="test 2"
等)。
¥Given the following test file, starting Node.js with the
--test-name-pattern="test [1-3]"
option would cause the test runner to execute
test 1
, test 2
, and test 3
. If test 1
did not match the test name
pattern, then its subtests would not execute, despite matching the pattern. The
same set of tests could also be executed by passing --test-name-pattern
multiple 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-pattern="/test [4-5]/i"
(或 --test-skip-pattern="/test [4-5]/i"
)启动 Node.js 将匹配 Test 4
和 Test 5
,因为该模式不区分大小写。
¥Test name patterns can also be specified using regular expression literals. This
allows regular expression flags to be used. In the previous example, starting
Node.js with --test-name-pattern="/test [4-5]/i"
(or --test-skip-pattern="/test [4-5]/i"
)
would match Test 4
and Test 5
because the pattern is case-insensitive.
要将单个测试与模式匹配,你可以使用其所有祖级测试名称作为前缀,并用空格分隔,以确保它是唯一的。例如,给定以下测试文件:
¥To match a single test with a pattern, you can prefix it with all its ancestor test names separated by space, to ensure it is unique. For example, given the following test file:
describe('test 1', (t) => {
it('some test');
});
describe('test 2', (t) => {
it('some test');
});
使用 --test-name-pattern="test 1 some test"
启动 Node.js 将仅匹配 test 1
中的 some test
。
¥Starting Node.js with --test-name-pattern="test 1 some test"
would match
only some test
in test 1
.
测试名称模式不会更改测试运行程序执行的文件集。
¥Test name patterns do not change the set of files that the test runner executes.
如果同时提供了 --test-name-pattern
和 --test-skip-pattern
,则测试必须满足这两个要求才能执行。
¥If both --test-name-pattern
and --test-skip-pattern
are supplied,
tests must satisfy both requirements in order to be executed.
无关的异步活动#
¥Extraneous asynchronous activity
一旦测试函数完成执行,将在保持测试顺序的同时尽快报告结果。但是,测试函数可能会生成比测试本身寿命更长的异步活动。测试运行器处理此类活动,但不会延迟报告测试结果以适应它。
¥Once a test function finishes executing, the results are reported as quickly as possible while maintaining the order of the tests. However, it is possible for the test function to generate asynchronous activity that outlives the test itself. The test runner handles this type of activity, but does not delay the reporting of test results in order to accommodate it.
在下面的示例中,测试完成时仍然有两个 setImmediate()
操作未完成。第一个 setImmediate()
尝试创建新的子测试。因为父测试已经完成并输出结果,所以新的子测试立即标记为失败,稍后报告给 <TestsStream>。
¥In the following example, a test completes with two setImmediate()
operations still outstanding. The first setImmediate()
attempts to create a
new subtest. Because the parent test has already finished and output its
results, the new subtest is immediately marked as failed, and reported later
to the <TestsStream>.
第二个 setImmediate()
创建了 uncaughtException
事件。源自已完成测试的 uncaughtException
和 unhandledRejection
事件被 test
模块标记为失败,并由 <TestsStream> 在顶层报告为诊断警告。
¥The second setImmediate()
creates an uncaughtException
event.
uncaughtException
and unhandledRejection
events originating from a completed
test are marked as failed by the test
module and reported as diagnostic
warnings 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) => {
throw new Error('error1');
});
});
setImmediate(() => {
throw new Error('error2');
});
// The test finishes after this line.
});
监视模式#
¥Watch mode
¥Stability: 1 - Experimental
Node.js 测试运行器支持通过传递 --watch
标志以监视模式运行:
¥The Node.js test runner supports running in watch mode by passing the --watch
flag:
node --test --watch
在监视模式下,测试运行器将监视测试文件及其依赖的更改。当检测到变化时,测试运行器将重新运行受变化影响的测试。测试运行器将继续运行直到进程终止。
¥In watch mode, the test runner will watch for changes to test files and their dependencies. When a change is detected, the test runner will rerun the tests affected by the change. The test runner will continue to run until the process is terminated.
从命令行运行测试#
¥Running tests from the command line
可以通过传入 --test
标志从命令行调用 Node.js 测试运行程序:
¥The Node.js test runner can be invoked from the command line by passing the
--test
flag:
node --test
默认情况下,Node.js 将运行与这些模式匹配的所有文件:
¥By default, Node.js will run all files matching these patterns:
-
**/*.test.{cjs,mjs,js}
-
**/*-test.{cjs,mjs,js}
-
**/*_test.{cjs,mjs,js}
-
**/test-*.{cjs,mjs,js}
-
**/test.{cjs,mjs,js}
-
**/test/**/*.{cjs,mjs,js}
提供 --experimental-strip-types
时,将匹配以下附加模式:
¥When --experimental-strip-types
is supplied, the following
additional patterns are matched:
-
**/*.test.{cts,mts,ts}
-
**/*-test.{cts,mts,ts}
-
**/*_test.{cts,mts,ts}
-
**/test-*.{cts,mts,ts}
-
**/test.{cts,mts,ts}
-
**/test/**/*.{cts,mts,ts}
或者,可以提供一个或多个 glob 模式作为 Node.js 命令的最终参数,如下所示。Glob 模式遵循 glob(7)
的行为。glob 模式应在命令行上用双引号引起来,以防止 shell 扩展,从而降低跨系统的可移植性。
¥Alternatively, one or more glob patterns can be provided as the
final argument(s) to the Node.js command, as shown below.
Glob patterns follow the behavior of glob(7)
.
The glob patterns should be enclosed in double quotes on the command line to
prevent shell expansion, which can reduce portability across systems.
node --test "**/*.test.js" "**/*.spec.js"
匹配文件作为测试文件执行。有关测试文件执行的更多信息可以在 测试运行器执行模型 部分找到。
¥Matching files are executed as test files. More information on the test file execution can be found in the test runner execution model section.
测试运行器执行模型#
¥Test runner execution model
当启用进程级测试隔离时,每个匹配的测试文件都会在单独的子进程中执行。任何时候运行的子进程的最大数量由 --test-concurrency
标志控制。如果子进程以退出代码 0 结束,则认为测试通过。否则,认为测试失败。测试文件必须是 Node.js 可执行文件,但不需要在内部使用 node:test
模块。
¥When process-level test isolation is enabled, each matching test file is
executed in a separate child process. The maximum number of child processes
running at any time is controlled by the --test-concurrency
flag. If the
child process finishes with an exit code of 0, the test is considered passing.
Otherwise, the test is considered to be a failure. Test files must be executable
by Node.js, but are not required to use the node:test
module internally.
每个测试文件都像常规脚本一样执行。也就是说,如果测试文件本身使用 node:test
来定义测试,则所有这些测试都将在单个应用线程中执行,而不管 test()
的 concurrency
选项的值如何。
¥Each test file is executed as if it was a regular script. That is, if the test
file itself uses node:test
to define tests, all of those tests will be
executed within a single application thread, regardless of the value of the
concurrency
option of test()
.
当禁用进程级测试隔离时,每个匹配的测试文件都会导入到测试运行器进程中。加载所有测试文件后,将以并发数 1 执行顶层测试。由于测试文件都在同一个上下文中运行,因此测试可以以启用隔离时不可能的方式相互交互。例如,如果测试依赖于全局状态,则该状态可能会被源自另一个文件的测试修改。
¥When process-level test isolation is disabled, each matching test file is imported into the test runner process. Once all test files have been loaded, the top level tests are executed with a concurrency of one. Because the test files are all run within the same context, it is possible for tests to interact with each other in ways that are not possible when isolation is enabled. For example, if a test relies on global state, it is possible for that state to be modified by a test originating from another file.
收集代码覆盖率#
¥Collecting code coverage
¥Stability: 1 - Experimental
当 Node.js 以 --experimental-test-coverage
命令行标志启动时,代码覆盖率将被收集并在所有测试完成后报告统计信息。如果使用 NODE_V8_COVERAGE
环境变量指定代码覆盖目录,则生成的 V8 覆盖文件写入该目录。默认情况下,node_modules/
目录中的 Node.js 核心模块和文件不包含在覆盖率报告中。但是,它们可以通过 --test-coverage-include
标志明确包含。如果启用覆盖,覆盖报告将通过 'test:coverage'
事件发送到任何 测试报告器。
¥When Node.js is started with the --experimental-test-coverage
command-line flag, code coverage is collected and statistics are reported once
all tests have completed. If the NODE_V8_COVERAGE
environment variable is
used to specify a code coverage directory, the generated V8 coverage files are
written to that directory. Node.js core modules and files within
node_modules/
directories are, by default, not included in the coverage report.
However, they can be explicity included via the --test-coverage-include
flag. If
coverage is enabled, the coverage report is sent to any test reporters via
the 'test:coverage'
event.
可以使用以下注释语法在一系列行上禁用覆盖:
¥Coverage can be disabled on a series of lines using the following comment 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 the specified number of lines, coverage will be automatically reenabled. If the number 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');
}
覆盖报告器#
¥Coverage reporters
Tap 和 Spec 报告器将打印覆盖统计数据的摘要。还有一个 lcov 报告器,它将生成 lcov 文件,可用作深度覆盖报告。
¥The tap and spec reporters will print a summary of the coverage statistics. There is also an lcov reporter that will generate an lcov file which can be used as an in depth coverage report.
node --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info
-
此报告器未报告任何测试结果。
¥No test results are reported by this reporter.
-
此报告器最好与另一个报告器一起使用。
¥This reporter should ideally be used alongside another reporter.
模拟#
¥Mocking
node:test
模块支持通过顶层 mock
对象在测试期间进行模拟。以下示例创建了一个对将两个数字相加的函数的监视。间谍随后被用来断言该函数已按预期调用。
¥The node:test
module supports mocking during testing via a top-level mock
object. The following example creates a spy on a function that adds two numbers
together. The spy is then used to assert that the function was called as
expected.
import assert from '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.callCount(), 0);
assert.strictEqual(sum(3, 4), 7);
assert.strictEqual(sum.mock.callCount(), 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.callCount(), 0);
assert.strictEqual(sum(3, 4), 7);
assert.strictEqual(sum.mock.callCount(), 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();
});
相同的模拟功能也暴露在每个测试的 TestContext
对象上。以下示例使用 TestContext
上公开的 API 创建对象方法的监听器。通过测试上下文进行模拟的好处是,测试运行器将在测试完成后自动恢复所有模拟功能。
¥The same mocking functionality is also exposed on the TestContext
object
of each test. The following example creates a spy on an object method using the
API exposed on the TestContext
. The benefit of mocking via the test context is
that the test runner will automatically restore all mocked functionality once
the test finishes.
test('spies on an object method', (t) => {
const number = {
value: 5,
add(a) {
return this.value + a;
},
};
t.mock.method(number, 'add');
assert.strictEqual(number.add.mock.callCount(), 0);
assert.strictEqual(number.add(3), 8);
assert.strictEqual(number.add.mock.callCount(), 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
模拟定时器是软件测试中常用的一种技术,用于模拟和控制定时器(例如 setInterval
和 setTimeout
)的行为,而无需实际等待指定的时间间隔。
¥Mocking timers is a technique commonly used in software testing to simulate and
control the behavior of timers, such as setInterval
and setTimeout
,
without actually waiting for the specified time intervals.
有关方法和功能的完整列表,请参阅 MockTimers
类。
¥Refer to the MockTimers
class for a full list of methods and features.
这使得开发者能够为时间相关的功能编写更可靠和可预测的测试。
¥This allows developers to write more reliable and predictable tests for time-dependent functionality.
下面的示例展示了如何模拟 setTimeout
。使用 .enable({ apis: ['setTimeout'] });
它将模拟 node:timers 和 node:timers/promises 模块以及 Node.js 全局上下文中的 setTimeout
函数。
¥The example below shows how to mock setTimeout
.
Using .enable({ apis: ['setTimeout'] });
it will mock the setTimeout
functions in the node:timers and
node:timers/promises modules,
as well as from the Node.js global context.
注意:该 API 目前不支持 import { setTimeout } from 'node:timers'
等解构函数。
¥Note: Destructuring functions such as
import { setTimeout } from 'node:timers'
is currently not supported by this API.
import assert from '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({ apis: ['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({ apis: ['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();
});
每个测试的 TestContext
对象的模拟属性中也公开了相同的模拟功能。通过测试上下文进行模拟的好处是,一旦测试完成,测试运行器将自动恢复所有模拟的定时器功能。
¥The same mocking functionality is also exposed in the mock property on the TestContext
object
of each test. The benefit of mocking via the test context is
that the test runner will automatically restore all mocked timers
functionality once the test finishes.
import assert from '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({ apis: ['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({ apis: ['setTimeout'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
// Advance in time
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
});
日期#
¥Dates
模拟定时器 API 还允许模拟 Date
对象。对于测试与时间相关的功能或模拟内部日历功能(例如 Date.now()
)来说,这是一个有用的功能。
¥The mock timers API also allows the mocking of the Date
object. This is a
useful feature for testing time-dependent functionality, or to simulate
internal calendar functions such as Date.now()
.
日期实现也是 MockTimers
类的一部分。请参阅它以获取方法和功能的完整列表。
¥The dates implementation is also part of the MockTimers
class. Refer to it
for a full list of methods and features.
注意:当一起模拟时,日期和定时器是依赖的。这意味着,如果你同时模拟了 Date
和 setTimeout
,则提前时间也会提前模拟日期,因为它们模拟单个内部时钟。
¥Note: Dates and timers are dependent when mocked together. This means that
if you have both the Date
and setTimeout
mocked, advancing the time will
also advance the mocked date as they simulate a single internal clock.
下面的示例展示了如何模拟 Date
对象并获取当前 Date.now()
值。
¥The example below show how to mock the Date
object and obtain the current
Date.now()
value.
import assert from 'node:assert';
import { test } from 'node:test';
test('mocks the Date object', (context) => {
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['Date'] });
// If not specified, the initial date will be based on 0 in the UNIX epoch
assert.strictEqual(Date.now(), 0);
// Advance in time will also advance the date
context.mock.timers.tick(9999);
assert.strictEqual(Date.now(), 9999);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('mocks the Date object', (context) => {
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['Date'] });
// If not specified, the initial date will be based on 0 in the UNIX epoch
assert.strictEqual(Date.now(), 0);
// Advance in time will also advance the date
context.mock.timers.tick(9999);
assert.strictEqual(Date.now(), 9999);
});
如果没有设置初始纪元,则初始日期将以 Unix 纪元中的 0 为基础。这是 1970 年 1 月 1 日 00:00:00 UTC。你可以通过将 now
属性传递给 .enable()
方法来设置初始日期。该值将用作模拟 Date
对象的初始日期。它可以是正整数,也可以是另一个 Date 对象。
¥If there is no initial epoch set, the initial date will be based on 0 in the
Unix epoch. This is January 1st, 1970, 00:00:00 UTC. You can set an initial date
by passing a now
property to the .enable()
method. This value will be used
as the initial date for the mocked Date
object. It can either be a positive
integer, or another Date object.
import assert from 'node:assert';
import { test } from 'node:test';
test('mocks the Date object with initial time', (context) => {
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['Date'], now: 100 });
assert.strictEqual(Date.now(), 100);
// Advance in time will also advance the date
context.mock.timers.tick(200);
assert.strictEqual(Date.now(), 300);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('mocks the Date object with initial time', (context) => {
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['Date'], now: 100 });
assert.strictEqual(Date.now(), 100);
// Advance in time will also advance the date
context.mock.timers.tick(200);
assert.strictEqual(Date.now(), 300);
});
你可以使用 .setTime()
方法手动将模拟日期移动到另一个时间。此方法仅接受正整数。
¥You can use the .setTime()
method to manually move the mocked date to another
time. This method only accepts a positive integer.
注意:此方法将执行新时间过去的任何模拟定时器。
¥Note: This method will execute any mocked timers that are in the past from the new time.
在下面的示例中,我们为模拟日期设置新时间。
¥In the below example we are setting a new time for the mocked date.
import assert from 'node:assert';
import { test } from 'node:test';
test('sets the time of a date object', (context) => {
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['Date'], now: 100 });
assert.strictEqual(Date.now(), 100);
// Advance in time will also advance the date
context.mock.timers.setTime(1000);
context.mock.timers.tick(200);
assert.strictEqual(Date.now(), 1200);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('sets the time of a date object', (context) => {
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['Date'], now: 100 });
assert.strictEqual(Date.now(), 100);
// Advance in time will also advance the date
context.mock.timers.setTime(1000);
context.mock.timers.tick(200);
assert.strictEqual(Date.now(), 1200);
});
如果你有任何设置为过去运行的定时器,它将像调用 .tick()
方法一样执行。如果你想测试已经过去的时间相关功能,这非常有用。
¥If you have any timer that's set to run in the past, it will be executed as if
the .tick()
method has been called. This is useful if you want to test
time-dependent functionality that's already in the past.
import assert from 'node:assert';
import { test } from 'node:test';
test('runs timers as setTime passes ticks', (context) => {
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const fn = context.mock.fn();
setTimeout(fn, 1000);
context.mock.timers.setTime(800);
// Timer is not executed as the time is not yet reached
assert.strictEqual(fn.mock.callCount(), 0);
assert.strictEqual(Date.now(), 800);
context.mock.timers.setTime(1200);
// Timer is executed as the time is now reached
assert.strictEqual(fn.mock.callCount(), 1);
assert.strictEqual(Date.now(), 1200);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('runs timers as setTime passes ticks', (context) => {
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const fn = context.mock.fn();
setTimeout(fn, 1000);
context.mock.timers.setTime(800);
// Timer is not executed as the time is not yet reached
assert.strictEqual(fn.mock.callCount(), 0);
assert.strictEqual(Date.now(), 800);
context.mock.timers.setTime(1200);
// Timer is executed as the time is now reached
assert.strictEqual(fn.mock.callCount(), 1);
assert.strictEqual(Date.now(), 1200);
});
使用 .runAll()
将执行当前队列中的所有定时器。这还将模拟日期提前到最后执行的定时器的时间,就好像时间已经过去一样。
¥Using .runAll()
will execute all timers that are currently in the queue. This
will also advance the mocked date to the time of the last timer that was
executed as if the time has passed.
import assert from 'node:assert';
import { test } from 'node:test';
test('runs timers as setTime passes ticks', (context) => {
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const fn = context.mock.fn();
setTimeout(fn, 1000);
setTimeout(fn, 2000);
setTimeout(fn, 3000);
context.mock.timers.runAll();
// All timers are executed as the time is now reached
assert.strictEqual(fn.mock.callCount(), 3);
assert.strictEqual(Date.now(), 3000);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('runs timers as setTime passes ticks', (context) => {
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const fn = context.mock.fn();
setTimeout(fn, 1000);
setTimeout(fn, 2000);
setTimeout(fn, 3000);
context.mock.timers.runAll();
// All timers are executed as the time is now reached
assert.strictEqual(fn.mock.callCount(), 3);
assert.strictEqual(Date.now(), 3000);
});
快照测试#
¥Snapshot testing
¥Stability: 1.0 - Early development
快照测试允许将任意值序列化为字符串值并与一组已知的良好值进行比较。已知的良好值称为快照,并存储在快照文件中。快照文件由测试运行器管理,但设计为人类可读的,以帮助调试。最佳做法是将快照文件与测试文件一起签入源代码控制。为了启用快照测试,必须使用 --experimental-test-snapshots
命令行标志启动 Node.js。
¥Snapshot tests allow arbitrary values to be serialized into string values and
compared against a set of known good values. The known good values are known as
snapshots, and are stored in a snapshot file. Snapshot files are managed by the
test runner, but are designed to be human readable to aid in debugging. Best
practice is for snapshot files to be checked into source control along with your
test files. In order to enable snapshot testing, Node.js must be started with
the --experimental-test-snapshots
command-line flag.
快照文件是通过使用 --test-update-snapshots
命令行标志启动 Node.js 生成的。为每个测试文件生成一个单独的快照文件。默认情况下,快照文件的名称与测试文件相同,但文件扩展名为 .snapshot
。可以使用 snapshot.setResolveSnapshotPath()
函数配置此行为。每个快照断言对应快照文件中的导出。
¥Snapshot files are generated by starting Node.js with the
--test-update-snapshots
command-line flag. A separate snapshot file is
generated for each test file. By default, the snapshot file has the same name
as the test file with a .snapshot
file extension. This behavior can be
configured using the snapshot.setResolveSnapshotPath()
function. Each
snapshot assertion corresponds to an export in the snapshot file.
下面显示了一个示例快照测试。第一次执行此测试时,它将失败,因为相应的快照文件不存在。
¥An example snapshot test is shown below. The first time this test is executed, it will fail because the corresponding snapshot file does not exist.
// test.js
suite('suite of snapshot tests', () => {
test('snapshot test', (t) => {
t.assert.snapshot({ value1: 1, value2: 2 });
t.assert.snapshot(5);
});
});
通过使用 --test-update-snapshots
运行测试文件来生成快照文件。测试应该通过,并且在与测试文件相同的目录中创建一个名为 test.js.snapshot
的文件。快照文件的内容如下所示。每个快照都由测试的全名和一个计数器标识,以区分同一测试中的快照。
¥Generate the snapshot file by running the test file with
--test-update-snapshots
. The test should pass, and a file named
test.js.snapshot
is created in the same directory as the test file. The
contents of the snapshot file are shown below. Each snapshot is identified by
the full name of test and a counter to differentiate between snapshots in the
same test.
exports[`suite of snapshot tests > snapshot test 1`] = `
{
"value1": 1,
"value2": 2
}
`;
exports[`suite of snapshot tests > snapshot test 2`] = `
5
`;
一旦创建了快照文件,请在没有 --test-update-snapshots
标志的情况下再次运行测试。测试现在应该通过。
¥Once the snapshot file is created, run the tests again without the
--test-update-snapshots
flag. The tests should pass now.
测试报告器#
¥Test reporters
node:test
模块支持传递 --test-reporter
标志,以便测试运行器使用特定的报告程序。
¥The node:test
module supports passing --test-reporter
flags for the test runner to use a specific reporter.
支持以下内置报告器:
¥The following built-reporters are supported:
-
tap
tap
报告器以 TAP 格式输出测试结果。¥
tap
Thetap
reporter outputs the test results in the TAP format. -
spec
spec
报告器以人类可读的格式输出测试结果。¥
spec
Thespec
reporter outputs the test results in a human-readable format. -
dot
dot
报告器以紧凑格式输出测试结果,其中每个通过的测试用.
表示,每个失败的测试用X
表示。¥
dot
Thedot
reporter outputs the test results in a compact format, where each passing test is represented by a.
, and each failing test is represented by aX
. -
junit
junit 报告器以 jUnit XML 格式输出测试结果¥
junit
The junit reporter outputs test results in a jUnit XML format -
lcov
与--experimental-test-coverage
标志一起使用时,lcov
报告器会输出测试覆盖率。¥
lcov
Thelcov
reporter outputs test coverage when used with the--experimental-test-coverage
flag.
当 stdout
为 TTY 时,默认使用 spec
报告器。否则,默认使用 tap
报告器。
¥When stdout
is a TTY, the spec
reporter is used by default.
Otherwise, the tap
reporter is used by default.
这些报告器的确切输出可能会因 Node.js 版本而异,不应以编程方式依赖。如果需要以编程方式访问测试运行程序的输出,请使用 <TestsStream> 触发的事件。
¥The exact output of these reporters is subject to change between versions of Node.js, and should not be relied on programmatically. If programmatic access to the test runner's output is required, use the events emitted by the <TestsStream>.
报告器可通过 node:test/reporters
模块获得:
¥The reporters are available via the node:test/reporters
module:
import { tap, spec, dot, junit, lcov } from 'node:test/reporters';
const { tap, spec, dot, junit, lcov } = require('node:test/reporters');
自定义报告器#
¥Custom reporters
--test-reporter
可用于指定自定义报告程序的路径。自定义报告器是一个导出 stream.compose 接受的值的模块。报告者应该转换 <TestsStream> 触发的事件
¥--test-reporter
can be used to specify a path to custom reporter.
A custom reporter is a module that exports a value
accepted by stream.compose.
Reporters should transform events emitted by a <TestsStream>
使用 <stream.Transform> 的自定义报告器示例:
¥Example of a custom reporter using <stream.Transform>:
import { Transform } from 'node:stream';
const customReporter = new Transform({
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;
}
}
},
});
export default customReporter;
const { Transform } = require('node:stream');
const customReporter = new Transform({
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:
export default async function * customReporter(source) {
for await (const event of source) {
switch (event.type) {
case 'test:dequeue':
yield `test ${event.data.name} dequeued\n`;
break;
case 'test:enqueue':
yield `test ${event.data.name} enqueued\n`;
break;
case 'test:watch:drained':
yield 'test watch queue drained\n';
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;
}
}
}
}
module.exports = async function * customReporter(source) {
for await (const event of source) {
switch (event.type) {
case 'test:dequeue':
yield `test ${event.data.name} dequeued\n`;
break;
case 'test:enqueue':
yield `test ${event.data.name} enqueued\n`;
break;
case 'test:watch:drained':
yield 'test watch queue drained\n';
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;
}
}
}
};
提供给 --test-reporter
的值应该是一个类似于 JavaScript 代码中的 import()
中使用的字符串,或者提供给 --import
的值。
¥The value provided to --test-reporter
should be a string like one used in an
import()
in JavaScript code, or a value provided for --import
.
多报告器#
¥Multiple reporters
可以多次指定 --test-reporter
标志,以多种格式报告测试结果。在这种情况下,需要使用 --test-reporter-destination
为每个报告者指定目标。目标可以是 stdout
、stderr
或文件路径。报告器和目标根据指定的顺序配对。
¥The --test-reporter
flag can be specified multiple times to report test
results in several formats. In this situation
it is required to specify a destination for each reporter
using --test-reporter-destination
.
Destination can be stdout
, stderr
, or a file path.
Reporters and destinations are paired according
to the order they were specified.
在下面的例子中,spec
报告器将输出到 stdout
,dot
报告器将输出到 file.txt
:
¥In the following example, the spec
reporter will output to stdout
,
and the dot
reporter will output to file.txt
:
node --test-reporter=spec --test-reporter=dot --test-reporter-destination=stdout --test-reporter-destination=file.txt
当指定单个报告者时,目标将默认为 stdout
,除非明确提供目标。
¥When a single reporter is specified, the destination will default to stdout
,
unless a destination is explicitly provided.
run([options])
#
-
options
<Object> 运行测试的配置选项。支持以下属性:¥
options
<Object> Configuration options for running tests. The following properties are supported:-
concurrency
<number> | <boolean> 如果提供了一个数字,那么许多测试进程将并行运行,其中每个进程对应一个测试文件。如果是true
,它将并行运行os.availableParallelism() - 1
个测试文件。如果是false
,它一次只会运行一个测试文件。默认值:false
。¥
concurrency
<number> | <boolean> If a number is provided, then that many test processes would run in parallel, where each process corresponds to one test file. Iftrue
, it would runos.availableParallelism() - 1
test files in parallel. Iffalse
, it would only run one test file at a time. Default:false
. -
files
:<Array> 包含要运行的文件列表的数组。默认值:来自 测试运行器执行模型 的匹配文件。¥
files
: <Array> An array containing the list of files to run. Default: matching files from test runner execution model. -
forceExit
:<boolean> 配置测试运行器在所有已知测试完成执行后退出进程,即使事件循环将保持活动状态。默认值:false
。¥
forceExit
: <boolean> Configures the test runner to exit the process once all known tests have finished executing even if the event loop would otherwise remain active. Default:false
. -
globPatterns
:<Array> 包含用于匹配测试文件的 glob 模式列表的数组。此选项不能与files
一起使用。默认值:来自 测试运行器执行模型 的匹配文件。¥
globPatterns
: <Array> An array containing the list of glob patterns to match test files. This option cannot be used together withfiles
. Default: matching files from test runner execution model. -
inspectPort
<number> | <Function> 设置测试子进程的检查器端口。这可以是数字,也可以是不带参数并返回数字的函数。如果提供了一个空值,每个进程都有自己的端口,从主进程的process.debugPort
递增。如果isolation
选项设置为'none'
,则忽略此选项,因为没有生成子进程。默认值:undefined
。¥
inspectPort
<number> | <Function> Sets inspector port of test child process. This can be a number, or a function that takes no arguments and returns a number. If a nullish value is provided, each process gets its own port, incremented from the primary'sprocess.debugPort
. This option is ignored if theisolation
option is set to'none'
as no child processes are spawned. Default:undefined
. -
isolation
<string> 配置测试隔离的类型。如果设置为'process'
,则每个测试文件都在单独的子进程中运行。如果设置为'none'
,则所有测试文件都在当前进程中运行。默认值:'process'
。¥
isolation
<string> Configures the type of test isolation. If set to'process'
, each test file is run in a separate child process. If set to'none'
, all test files run in the current process. Default:'process'
. -
only
:<boolean> 如果为真,测试上下文将仅运行设置了only
选项的测试¥
only
: <boolean> If truthy, the test context will only run tests that have theonly
option set -
setup
<Function> 接受TestsStream
实例并可用于在运行任何测试之前设置监听器的函数。默认值:undefined
。¥
setup
<Function> A function that accepts theTestsStream
instance and can be used to setup listeners before any tests are run. Default:undefined
. -
execArgv
<Array> 生成子进程时传递给node
可执行文件的 CLI 标志数组。当isolation
是'none
' 时,此选项无效。默认值:[]
¥
execArgv
<Array> An array of CLI flags to pass to thenode
executable when spawning the subprocesses. This option has no effect whenisolation
is'none
'. Default:[]
-
argv
<Array> 生成子进程时传递给每个测试文件的 CLI 标志数组。当isolation
是'none'
时,此选项无效。默认值:[]
。¥
argv
<Array> An array of CLI flags to pass to each test file when spawning the subprocesses. This option has no effect whenisolation
is'none'
. Default:[]
. -
signal
<AbortSignal> 允许中止正在进行的测试执行。¥
signal
<AbortSignal> Allows aborting an in-progress test execution. -
testNamePatterns
<string> | <RegExp> | <Array> 一个字符串、正则表达式或正则表达式数组,可用于仅运行名称与提供的模式匹配的测试。测试名称模式被解释为 JavaScript 正则表达式。对于执行的每个测试,也会运行任何相应的测试钩子,例如beforeEach()
。默认值:undefined
。¥
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
. -
testSkipPatterns
<string> | <RegExp> | <Array> 字符串、RegExp 或 RegExp 数组,可用于排除名称与提供的模式匹配的正在运行的测试。测试名称模式被解释为 JavaScript 正则表达式。对于执行的每个测试,也会运行任何相应的测试钩子,例如beforeEach()
。默认值:undefined
。¥
testSkipPatterns
<string> | <RegExp> | <Array> A String, RegExp or a RegExp Array, that can be used to exclude running 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> 测试执行将在几毫秒后失败。如果未指定,则子测试从其父测试继承此值。默认值:Infinity
。¥
timeout
<number> A number of milliseconds the test execution will fail after. If unspecified, subtests inherit this value from their parent. Default:Infinity
. -
watch
<boolean> 是否以监视模式运行。默认值:false
。¥
watch
<boolean> Whether to run in watch mode or not. Default:false
. -
shard
<Object> 在特定分片中运行测试。默认值:undefined
。¥
shard
<Object> Running tests in a specific shard. Default:undefined
.-
index
<number> 是 1 到<total>
之间的正整数,指定要运行的分片的索引。此选项是必需的。¥
index
<number> is a positive integer between 1 and<total>
that specifies the index of the shard to run. This option is required. -
total
<number> 是一个正整数,指定将测试文件拆分为的分片总数。此选项是必需的。¥
total
<number> is a positive integer that specifies the total number of shards to split the test files to. This option is required.
-
-
coverage
<boolean> 启用 代码覆盖率 集合。默认值:false
。¥
coverage
<boolean> enable code coverage collection. Default:false
. -
coverageExcludeGlobs
<string> | <Array> 使用 glob 模式从代码覆盖范围中排除特定文件,该模式可以匹配绝对和相对文件路径。此属性仅在coverage
设置为true
时适用。如果同时提供了coverageExcludeGlobs
和coverageIncludeGlobs
,则文件必须满足两个条件才能包含在覆盖率报告中。默认值:undefined
。¥
coverageExcludeGlobs
<string> | <Array> Excludes specific files from code coverage using a glob pattern, which can match both absolute and relative file paths. This property is only applicable whencoverage
was set totrue
. If bothcoverageExcludeGlobs
andcoverageIncludeGlobs
are provided, files must meet both criteria to be included in the coverage report. Default:undefined
. -
coverageIncludeGlobs
<string> | <Array> 使用 glob 模式在代码覆盖范围内包含特定文件,该模式可以匹配绝对和相对文件路径。此属性仅在coverage
设置为true
时适用。如果同时提供了coverageExcludeGlobs
和coverageIncludeGlobs
,则文件必须满足两个条件才能包含在覆盖率报告中。默认值:undefined
。¥
coverageIncludeGlobs
<string> | <Array> Includes specific files in code coverage using a glob pattern, which can match both absolute and relative file paths. This property is only applicable whencoverage
was set totrue
. If bothcoverageExcludeGlobs
andcoverageIncludeGlobs
are provided, files must meet both criteria to be included in the coverage report. Default:undefined
. -
lineCoverage
<number> 要求覆盖行的最小百分比。如果代码覆盖率未达到指定的阈值,则该过程将以代码1
退出。默认值:0
。¥
lineCoverage
<number> Require a minimum percent of covered lines. If code coverage does not reach the threshold specified, the process will exit with code1
. Default:0
. -
branchCoverage
<number> 要求覆盖分支的最小百分比。如果代码覆盖率未达到指定的阈值,则该过程将以代码1
退出。默认值:0
。¥
branchCoverage
<number> Require a minimum percent of covered branches. If code coverage does not reach the threshold specified, the process will exit with code1
. Default:0
. -
functionCoverage
<number> 要求覆盖函数的最小百分比。如果代码覆盖率未达到指定的阈值,则该过程将以代码1
退出。默认值:0
。¥
functionCoverage
<number> Require a minimum percent of covered functions. If code coverage does not reach the threshold specified, the process will exit with code1
. Default:0
.
-
-
¥Returns: <TestsStream>
注意:shard
用于跨机器或进程水平并行测试运行,非常适合跨不同环境的大规模执行。它与 watch
模式不兼容,该模式是通过自动重新运行文件更改测试来实现快速代码迭代而定制的。
¥Note: shard
is used to horizontally parallelize test running across
machines or processes, ideal for large-scale executions across varied
environments. It's incompatible with watch
mode, tailored for rapid
code iteration by automatically rerunning tests on file changes.
import { tap } from 'node:test/reporters';
import { run } from 'node:test';
import process from 'node:process';
import path from 'node:path';
run({ files: [path.resolve('./tests/test.js')] })
.on('test:fail', () => {
process.exitCode = 1;
})
.compose(tap)
.pipe(process.stdout);
const { tap } = require('node:test/reporters');
const { run } = require('node:test');
const path = require('node:path');
run({ files: [path.resolve('./tests/test.js')] })
.on('test:fail', () => {
process.exitCode = 1;
})
.compose(tap)
.pipe(process.stdout);
suite([name][, options][, fn])
#
-
name
<string> 套件名称,报告测试结果时显示。默认值:fn
的name
属性,如果fn
没有名称,则为'<anonymous>'
。¥
name
<string> The name of the suite, which is displayed when reporting test results. Default: Thename
property offn
, or'<anonymous>'
iffn
does not have a name. -
options
<Object> 套件的可选配置选项。这支持与test([name][, options][, fn])
相同的选项。¥
options
<Object> Optional configuration options for the suite. This supports the same options astest([name][, options][, fn])
. -
fn
<Function> | <AsyncFunction> suite 函数声明嵌套测试和套件。此函数的第一个参数是SuiteContext
对象。默认值:空操作函数。¥
fn
<Function> | <AsyncFunction> The suite function declaring nested tests and suites. The first argument to this function is aSuiteContext
object. Default: A no-op function. -
返回:<Promise> 立即满足
undefined
。¥Returns: <Promise> Immediately fulfilled with
undefined
.
suite()
函数是从 node:test
模块导入的。
¥The suite()
function is imported from the node:test
module.
suite.skip([name][, options][, fn])
#
跳过套件的简写。这与 suite([name], { skip: true }[, fn])
相同。
¥Shorthand for skipping a suite. This is the same as
suite([name], { skip: true }[, fn])
.
suite.todo([name][, options][, fn])
#
将套件标记为 TODO
的简写。这与 suite([name], { todo: true }[, fn])
相同。
¥Shorthand for marking a suite as TODO
. This is the same as
suite([name], { todo: true }[, fn])
.
suite.only([name][, options][, fn])
#
将套件标记为 only
的简写。这与 suite([name], { only: true }[, fn])
相同。
¥Shorthand for marking a suite as only
. This is the same as
suite([name], { only: true }[, fn])
.
test([name][, options][, fn])
#
-
name
<string> 测试的名称,报告测试结果时显示。默认值:fn
的name
属性,如果fn
没有名称,则为'<anonymous>'
。¥
name
<string> The name of the test, which is displayed when reporting test results. Default: Thename
property offn
, or'<anonymous>'
iffn
does not have a name. -
options
<Object> 测试的配置选项。支持以下属性:¥
options
<Object> Configuration options for the test. The following properties are supported:-
concurrency
<number> | <boolean> 如果提供了一个数字,那么许多测试将在应用线程中并行运行。如果为true
,则所有计划的异步测试在线程内同时运行。如果是false
,一次只运行一个测试。如果未指定,则子测试从其父测试继承此值。默认值:false
。¥
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 the thread. Iffalse
, only one test runs at a time. If unspecified, subtests inherit this value from their parent. Default:false
. -
only
<boolean> 如果为真,并且测试上下文配置为运行only
测试,则将运行此测试。否则跳过测试。默认值:false
。¥
only
<boolean> If truthy, and the test context is configured to runonly
tests, then this test will be run. Otherwise, the test is skipped. Default:false
. -
signal
<AbortSignal> 允许中止正在进行的测试。¥
signal
<AbortSignal> Allows aborting an in-progress test. -
skip
<boolean> | <string> 如果为真,则跳过测试。如果提供了字符串,则该字符串将作为跳过测试的原因显示在测试结果中。默认值:false
。¥
skip
<boolean> | <string> If truthy, the test is skipped. If a string is provided, that string is displayed in the test results as the reason for skipping the test. Default:false
. -
todo
<boolean> | <string> 如果为真,则测试标记为TODO
。如果提供了字符串,则该字符串会显示在测试结果中作为测试为TODO
的原因。默认值:false
。¥
todo
<boolean> | <string> If truthy, the test marked asTODO
. If a string is provided, that string is displayed in the test results as the reason why the test isTODO
. Default:false
. -
timeout
<number> 测试失败的毫秒数。如果未指定,则子测试从其父测试继承此值。默认值:Infinity
。¥
timeout
<number> A number of milliseconds the test will fail after. If unspecified, subtests inherit this value from their parent. Default:Infinity
. -
plan
<number> 预期在测试中运行的断言和子测试的数量。如果测试中运行的断言数量与计划中指定的数量不匹配,则测试将失败。默认值:undefined
。¥
plan
<number> The number of assertions and subtests expected to be run in the test. If the number of assertions run in the test does not match the number specified in the plan, the test will fail. Default:undefined
.
-
-
fn
<Function> | <AsyncFunction> 被测试的函数。此函数的第一个参数是TestContext
对象。如果测试使用回调,则回调函数作为第二个参数传入。默认值:空操作函数。¥
fn
<Function> | <AsyncFunction> The function under test. The first argument to this function is aTestContext
object. If the test uses callbacks, the callback function is passed as the second argument. Default: A no-op function. -
返回:<Promise> 一旦测试完成,或者如果测试在套件中运行,则立即满足
undefined
。¥Returns: <Promise> Fulfilled with
undefined
once the test completes, or immediately if the test runs within a suite.
test()
函数是从 test
模块导入的值。每次调用此函数都会向 <TestsStream> 报告测试。
¥The test()
function is the value imported from the test
module. Each
invocation of this function results in reporting the test to the <TestsStream>.
传给 fn
参数的 TestContext
对象可用于执行与当前测试相关的操作。示例包括跳过测试、添加额外的诊断信息或创建子测试。
¥The TestContext
object passed to the fn
argument can be used to perform
actions related to the current test. Examples include skipping the test, adding
additional diagnostic information, or creating subtests.
test()
返回测试完成后满足的 Promise
。如果 test()
在套件内被调用,它会立即执行。返回值通常可以被顶层测试丢弃。但是,应该使用子测试的返回值来防止父测试先完成并取消子测试,如下例所示。
¥test()
returns a Promise
that fulfills once the test completes.
if test()
is called within a suite, it fulfills immediately.
The return value can usually be discarded for top level tests.
However, the return value from subtests should be used to prevent the parent
test from finishing first and cancelling the subtest
as 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) => {
return new Promise((resolve, reject) => {
setTimeout(resolve, 1000);
});
});
});
如果完成时间超过 timeout
毫秒,则可以使用 timeout
选项使测试失败。但是,它不是取消测试的可靠机制,因为正在运行的测试可能会阻塞应用线程,从而阻止预定的取消。
¥The timeout
option can be used to fail the test if it takes longer than
timeout
milliseconds to complete. However, it is not a reliable mechanism for
canceling tests because a running test might block the application thread and
thus prevent the scheduled cancellation.
test.skip([name][, options][, fn])
#
跳过测试的简写,与 test([name], { skip: true }[, fn])
相同。
¥Shorthand for skipping a test,
same as test([name], { skip: true }[, fn])
.
test.todo([name][, options][, fn])
#
将测试标记为 TODO
的简写,与 test([name], { todo: true }[, fn])
相同。
¥Shorthand for marking a test as TODO
,
same as test([name], { todo: true }[, fn])
.
test.only([name][, options][, fn])
#
将测试标记为 only
的简写,与 test([name], { only: true }[, fn])
相同。
¥Shorthand for marking a test as only
,
same as test([name], { only: true }[, fn])
.
describe([name][, options][, fn])
#
suite()
的别名。
¥Alias for suite()
.
describe()
函数是从 node:test
模块导入的。
¥The describe()
function is imported from the node:test
module.
describe.skip([name][, options][, fn])
#
跳过套件的简写。这与 describe([name], { skip: true }[, fn])
相同。
¥Shorthand for skipping a suite. This is the same as
describe([name], { skip: true }[, fn])
.
describe.todo([name][, options][, fn])
#
将套件标记为 TODO
的简写。这与 describe([name], { todo: true }[, fn])
相同。
¥Shorthand for marking a suite as TODO
. This is the same as
describe([name], { todo: true }[, fn])
.
describe.only([name][, options][, fn])
#
将套件标记为 only
的简写。这与 describe([name], { only: true }[, fn])
相同。
¥Shorthand for marking a suite as only
. This is the same as
describe([name], { only: true }[, fn])
.
it([name][, options][, fn])
#
test()
的别名。
¥Alias for test()
.
it()
函数是从 node:test
模块导入的。
¥The it()
function is imported from the node:test
module.
it.skip([name][, options][, fn])
#
跳过测试的简写,与 it([name], { skip: true }[, fn])
相同。
¥Shorthand for skipping a test,
same as it([name], { skip: true }[, fn])
.
it.todo([name][, options][, fn])
#
将测试标记为 TODO
的简写,与 it([name], { todo: true }[, fn])
相同。
¥Shorthand for marking a test as TODO
,
same as it([name], { todo: true }[, fn])
.
it.only([name][, options][, fn])
#
将测试标记为 only
的简写,与 it([name], { only: true }[, fn])
相同。
¥Shorthand for marking a test as only
,
same as it([name], { only: true }[, fn])
.
before([fn][, options])
#
-
fn
<Function> | <AsyncFunction> 钩子函数。如果钩子使用回调,则回调函数作为第二个参数传入。默认值:空操作函数。¥
fn
<Function> | <AsyncFunction> The hook function. If the hook uses callbacks, the callback function is passed as the second argument. Default: A no-op function. -
options
<Object> 钩子的配置选项。支持以下属性:¥
options
<Object> Configuration options for the hook. The following properties are supported:-
signal
<AbortSignal> 允许中止正在进行的钩子。¥
signal
<AbortSignal> Allows aborting an in-progress hook. -
timeout
<number> 钩子会在几毫秒后失败。如果未指定,则子测试从其父测试继承此值。默认值:Infinity
。¥
timeout
<number> A number of milliseconds the hook will fail after. If unspecified, subtests inherit this value from their parent. Default:Infinity
.
-
该函数创建一个在执行套件之前运行的钩子。
¥This function creates a hook that runs before executing 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> 钩子函数。如果钩子使用回调,则回调函数作为第二个参数传入。默认值:空操作函数。¥
fn
<Function> | <AsyncFunction> The hook function. If the hook uses callbacks, the callback function is passed as the second argument. Default: A no-op function. -
options
<Object> 钩子的配置选项。支持以下属性:¥
options
<Object> Configuration options for the hook. The following properties are supported:-
signal
<AbortSignal> 允许中止正在进行的钩子。¥
signal
<AbortSignal> Allows aborting an in-progress hook. -
timeout
<number> 钩子会在几毫秒后失败。如果未指定,则子测试从其父测试继承此值。默认值:Infinity
。¥
timeout
<number> A number of milliseconds the hook will fail after. If unspecified, subtests inherit this value from their parent. Default:Infinity
.
-
该函数创建一个在执行套件后运行的钩子。
¥This function creates a hook that runs after executing a suite.
describe('tests', async () => {
after(() => console.log('finished running tests'));
it('is a subtest', () => {
assert.ok('some relevant assertion here');
});
});
注意:即使套件内的测试失败,after
钩子也能保证运行。
¥Note: The after
hook is guaranteed to run,
even if tests within the suite fail.
beforeEach([fn][, options])
#
-
fn
<Function> | <AsyncFunction> 钩子函数。如果钩子使用回调,则回调函数作为第二个参数传入。默认值:空操作函数。¥
fn
<Function> | <AsyncFunction> The hook function. If the hook uses callbacks, the callback function is passed as the second argument. Default: A no-op function. -
options
<Object> 钩子的配置选项。支持以下属性:¥
options
<Object> Configuration options for the hook. The following properties are supported:-
signal
<AbortSignal> 允许中止正在进行的钩子。¥
signal
<AbortSignal> Allows aborting an in-progress hook. -
timeout
<number> 钩子会在几毫秒后失败。如果未指定,则子测试从其父测试继承此值。默认值:Infinity
。¥
timeout
<number> A number of milliseconds the hook will fail after. If unspecified, subtests inherit this value from their parent. Default:Infinity
.
-
此函数创建一个在当前套件中的每个测试之前运行的钩子。
¥This function creates a hook that runs before each test in 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> 钩子函数。如果钩子使用回调,则回调函数作为第二个参数传入。默认值:空操作函数。¥
fn
<Function> | <AsyncFunction> The hook function. If the hook uses callbacks, the callback function is passed as the second argument. Default: A no-op function. -
options
<Object> 钩子的配置选项。支持以下属性:¥
options
<Object> Configuration options for the hook. The following properties are supported:-
signal
<AbortSignal> 允许中止正在进行的钩子。¥
signal
<AbortSignal> Allows aborting an in-progress hook. -
timeout
<number> 钩子会在几毫秒后失败。如果未指定,则子测试从其父测试继承此值。默认值:Infinity
。¥
timeout
<number> A number of milliseconds the hook will fail after. If unspecified, subtests inherit this value from their parent. Default:Infinity
.
-
该函数创建一个钩子,在当前套件中的每个测试之后运行。即使测试失败,afterEach()
钩子也会运行。
¥This function creates a hook that runs after each test in the current suite.
The afterEach()
hook is run even if the test fails.
describe('tests', async () => {
afterEach(() => console.log('finished running a test'));
it('is a subtest', () => {
assert.ok('some relevant assertion here');
});
});
snapshot
#
¥Stability: 1.0 - Early development
其方法用于配置当前进程中的默认快照设置的对象。通过将通用配置代码放在预加载了 --require
或 --import
的模块中,可以将相同的配置应用于所有文件。
¥An object whose methods are used to configure default snapshot settings in the
current process. It is possible to apply the same configuration to all files by
placing common configuration code in a module preloaded with --require
or
--import
.
snapshot.setDefaultSnapshotSerializers(serializers)
#
¥Stability: 1.0 - Early development
-
serializers
<Array> 用作快照测试的默认序列化器的同步函数数组。¥
serializers
<Array> An array of synchronous functions used as the default serializers for snapshot tests.
此函数用于自定义测试运行器使用的默认序列化机制。默认情况下,测试运行器通过对提供的值调用 JSON.stringify(value, null, 2)
来执行序列化。JSON.stringify()
在循环结构和支持的数据类型方面确实存在限制。如果需要更强大的序列化机制,则应使用此函数。
¥This function is used to customize the default serialization mechanism used by
the test runner. By default, the test runner performs serialization by calling
JSON.stringify(value, null, 2)
on the provided value. JSON.stringify()
does
have limitations regarding circular structures and supported data types. If a
more robust serialization mechanism is required, this function should be used.
snapshot.setResolveSnapshotPath(fn)
#
¥Stability: 1.0 - Early development
-
fn
<Function> 用于计算快照文件位置的函数。该函数接收测试文件的路径作为其唯一参数。如果测试与文件无关(例如在 REPL 中),则输入未定义。fn()
必须返回一个字符串,指定快照文件的位置。¥
fn
<Function> A function used to compute the location of the snapshot file. The function receives the path of the test file as its only argument. If the test is not associated with a file (for example in the REPL), the input is undefined.fn()
must return a string specifying the location of the snapshot snapshot file.
此函数用于自定义用于快照测试的快照文件的位置。默认情况下,快照文件名与入口点文件名相同,但文件扩展名为 .snapshot
。
¥This function is used to customize the location of the snapshot file used for
snapshot testing. By default, the snapshot filename is the same as the entry
point filename with a .snapshot
file extension.
类:MockFunctionContext
#
¥Class: MockFunctionContext
MockFunctionContext
类用于检查或操纵通过 MockTracker
API 创建的模拟的行为。
¥The MockFunctionContext
class is used to inspect or manipulate the behavior of
mocks created via the MockTracker
APIs.
ctx.calls
#
返回用于跟踪模拟调用的内部数组副本的获取器。数组中的每个条目都是一个具有以下属性的对象。
¥A getter that returns a copy of the internal array used to track calls to the mock. Each entry in the array is an object with the following properties.
-
arguments
<Array> 传递给模拟函数的参数数组。¥
arguments
<Array> An array of the arguments passed to the mock function. -
error
<any> 如果模拟函数抛出,则此属性包含抛出的值。默认值:undefined
。¥
error
<any> If the mocked function threw then this property contains the thrown value. Default:undefined
. -
result
<any> 模拟函数返回的值。¥
result
<any> The value returned by the mocked function. -
stack
<Error> 一个Error
对象,其堆栈可用于确定模拟函数调用的调用点。¥
stack
<Error> AnError
object whose stack can be used to determine the callsite of the mocked function invocation. -
target
<Function> | <undefined> 如果模拟函数是构造函数,则此字段包含正在构造的类。否则这将是undefined
。¥
target
<Function> | <undefined> If the mocked function is a constructor, this field contains the class being constructed. Otherwise this will beundefined
. -
this
<any> 模拟函数的this
值。¥
this
<any> The mocked function'sthis
value.
ctx.callCount()
#
此函数返回此模拟已被调用的次数。此函数比检查 ctx.calls.length
更有效,因为 ctx.calls
是创建内部调用跟踪数组副本的获取器。
¥This function returns the number of times that this mock has been invoked. This
function is more efficient than checking ctx.calls.length
because ctx.calls
is a getter that creates a copy of the internal call tracking array.
ctx.mockImplementation(implementation)
#
-
implementation
<Function> | <AsyncFunction> 要用作模拟的新实现的函数。¥
implementation
<Function> | <AsyncFunction> The function to be used as the mock's new implementation.
此函数用于更改现有模拟的行为。
¥This function is used to change the behavior of an existing mock.
以下示例使用 t.mock.fn()
创建模拟函数,调用模拟函数,然后将模拟实现更改为不同的函数。
¥The following example creates a mock function using t.mock.fn()
, calls the
mock function, and then changes the mock implementation to a different function.
test('changes a mock behavior', (t) => {
let cnt = 0;
function addOne() {
cnt++;
return cnt;
}
function addTwo() {
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> 要用作onCall
指定的调用编号的模拟实现的函数。¥
implementation
<Function> | <AsyncFunction> The function to be used as the mock's implementation for the invocation number specified byonCall
. -
onCall
<integer> 将使用implementation
的调用编号。如果指定的调用已经发生,则抛出异常。默认值:下一次调用的次数。¥
onCall
<integer> The invocation number that will useimplementation
. If the specified invocation has already occurred then an exception is thrown. Default: The number of the next invocation.
此函数用于更改单个调用的现有模拟的行为。一旦调用 onCall
发生,模拟将恢复到没有调用 mockImplementationOnce()
时它会使用的任何行为。
¥This function is used to change the behavior of an existing mock for a single
invocation. Once invocation onCall
has occurred, the mock will revert to
whatever behavior it would have used had mockImplementationOnce()
not been
called.
以下示例使用 t.mock.fn()
创建模拟函数,调用模拟函数,将模拟实现更改为下一次调用的不同函数,然后恢复其先前的行为。
¥The following example creates a mock function using t.mock.fn()
, calls the
mock function, changes the mock implementation to a different function for the
next invocation, and then resumes its previous behavior.
test('changes a mock behavior once', (t) => {
let cnt = 0;
function addOne() {
cnt++;
return cnt;
}
function addTwo() {
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. The mock can still be used after calling this function.
类:MockModuleContext
#
¥Class: MockModuleContext
¥Stability: 1.0 - Early development
MockModuleContext
类用于操纵通过 MockTracker
API 创建的模块模拟的行为。
¥The MockModuleContext
class is used to manipulate the behavior of module mocks
created via the MockTracker
APIs.
ctx.restore()
#
重置模拟模块的实现。
¥Resets the implementation of the mock module.
类:MockTracker
#
¥Class: MockTracker
MockTracker
类用于管理模拟功能。测试运行器模块提供了一个顶层 mock
导出,它是一个 MockTracker
实例。每个测试还通过测试上下文的 mock
属性提供自己的 MockTracker
实例。
¥The MockTracker
class is used to manage mocking functionality. The test runner
module provides a top level mock
export which is a MockTracker
instance.
Each test also provides its own MockTracker
instance via the test context's
mock
property.
mock.fn([original[, implementation]][, options])
#
-
original
<Function> | <AsyncFunction> 创建模拟的可选函数。默认值:空操作函数。¥
original
<Function> | <AsyncFunction> An optional function to create a mock on. Default: A no-op function. -
implementation
<Function> | <AsyncFunction> 用作original
的模拟实现的可选函数。这对于创建针对指定次数的调用表现出一种行为然后恢复original
的行为的模拟非常有用。默认值:original
指定的函数。¥
implementation
<Function> | <AsyncFunction> An optional function used as the mock implementation fororiginal
. This is useful for creating mocks that exhibit one behavior for a specified number of calls and then restore the behavior oforiginal
. Default: The function specified byoriginal
. -
options
<Object> 模拟功能的可选配置选项。支持以下属性:¥
options
<Object> Optional configuration options for the mock function. The following properties are supported:-
times
<integer> 模拟将使用implementation
的行为的次数。一旦模拟函数被调用了times
次,它会自动恢复original
的行为。此值必须是大于零的整数。默认值:Infinity
。¥
times
<integer> The number of times that the mock will use the behavior ofimplementation
. Once the mock function has been calledtimes
times, it will automatically restore the behavior oforiginal
. This value must be an integer greater than zero. Default:Infinity
.
-
-
返回:<Proxy> 模拟函数。模拟函数包含一个特殊的
mock
属性,它是MockFunctionContext
的一个实例,可用于检查和更改模拟函数的行为。¥Returns: <Proxy> The mocked function. The mocked function contains a special
mock
property, which is an instance ofMockFunctionContext
, and can be used for inspecting and changing the behavior of the mocked function.
此函数用于创建模拟函数。
¥This function is used to create a mock function.
以下示例创建了一个模拟函数,每次调用时计数器都会递增 1。times
选项用于修改模拟行为,以便前两次调用将两个而不是一个添加到计数器。
¥The following example creates a mock function that increments a counter by one
on each invocation. The times
option is used to modify the mock behavior such
that the first two invocations add two to the counter instead of one.
test('mocks a counting function', (t) => {
let cnt = 0;
function addOne() {
cnt++;
return cnt;
}
function addTwo() {
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])
#
此函数是 MockTracker.method
的语法糖,options.getter
设置为 true
。
¥This function is syntax sugar for MockTracker.method
with options.getter
set to true
.
mock.method(object, methodName[, implementation][, options])
#
-
object
<Object> 其方法被模拟的对象。¥
object
<Object> The object whose method is being mocked. -
methodName
<string> | <symbol> 要模拟的object
上的方法的标识符。如果object[methodName]
不是函数,则会抛出错误。¥
methodName
<string> | <symbol> The identifier of the method onobject
to mock. Ifobject[methodName]
is not a function, an error is thrown. -
implementation
<Function> | <AsyncFunction> 用作object[methodName]
的模拟实现的可选函数。默认值:object[methodName]
指定的原始方法。¥
implementation
<Function> | <AsyncFunction> An optional function used as the mock implementation forobject[methodName]
. Default: The original method specified byobject[methodName]
. -
options
<Object> 模拟方法的可选配置选项。支持以下属性:¥
options
<Object> Optional configuration options for the mock method. The following properties are supported:-
getter
<boolean> 如果为true
,object[methodName]
被当作获取器。此选项不能与setter
选项一起使用。默认值:false。¥
getter
<boolean> Iftrue
,object[methodName]
is treated as a getter. This option cannot be used with thesetter
option. Default: false. -
setter
<boolean> 如果为true
,object[methodName]
被视为设置器。此选项不能与getter
选项一起使用。默认值:false。¥
setter
<boolean> Iftrue
,object[methodName]
is treated as a setter. This option cannot be used with thegetter
option. Default: false. -
times
<integer> 模拟将使用implementation
的行为的次数。一旦被模拟的方法被调用了times
次,它会自动恢复原来的行为。此值必须是大于零的整数。默认值:Infinity
。¥
times
<integer> The number of times that the mock will use the behavior ofimplementation
. Once the mocked method has been calledtimes
times, it will automatically restore the original behavior. This value must be an integer greater than zero. Default:Infinity
.
-
-
返回:<Proxy> 被模拟的方法。模拟方法包含一个特殊的
mock
属性,它是MockFunctionContext
的实例,可用于检查和更改模拟方法的行为。¥Returns: <Proxy> The mocked method. The mocked method contains a special
mock
property, which is an instance ofMockFunctionContext
, and can be used for inspecting and changing the behavior of the mocked method.
此函数用于在现有对象方法上创建模拟。以下示例演示了如何在现有对象方法上创建模拟。
¥This function is used to create a mock on an existing object method. The following example demonstrates how a mock is created on an existing object method.
test('spies on an object method', (t) => {
const number = {
value: 5,
subtract(a) {
return this.value - a;
},
};
t.mock.method(number, 'subtract');
assert.strictEqual(number.subtract.mock.callCount(), 0);
assert.strictEqual(number.subtract(3), 2);
assert.strictEqual(number.subtract.mock.callCount(), 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.module(specifier[, options])
#
¥Stability: 1.0 - Early development
-
specifier
<string> | <URL> 用于标识要模拟的模块的字符串。¥
specifier
<string> | <URL> A string identifying the module to mock. -
options
<Object> 模拟模块的可选配置选项。支持以下属性:¥
options
<Object> Optional configuration options for the mock module. The following properties are supported:-
cache
<boolean> 如果false
,则每次调用require()
或import()
都会生成一个新的模拟模块。如果是true
,后续调用将返回相同的模块模拟,并且模拟模块将插入到 CommonJS 缓存中。默认值:false。¥
cache
<boolean> Iffalse
, each call torequire()
orimport()
generates a new mock module. Iftrue
, subsequent calls will return the same module mock, and the mock module is inserted into the CommonJS cache. Default: false. -
defaultExport
<any> 用作模拟模块默认导出的可选值。如果未提供此值,则 ESM 模拟不包含默认导出。如果模拟是 CommonJS 或内置模块,则此设置用作module.exports
的值。如果没有提供此值,CJS 和内置模拟将使用空对象作为module.exports
的值。¥
defaultExport
<any> An optional value used as the mocked module's default export. If this value is not provided, ESM mocks do not include a default export. If the mock is a CommonJS or builtin module, this setting is used as the value ofmodule.exports
. If this value is not provided, CJS and builtin mocks use an empty object as the value ofmodule.exports
. -
namedExports
<Object> 可选对象,其键和值用于创建模拟模块的命名导出。如果模拟是 CommonJS 或内置模块,则这些值将复制到module.exports
上。因此,如果使用命名导出和非对象默认导出创建模拟,则模拟在用作 CJS 或内置模块时将引发异常。¥
namedExports
<Object> An optional object whose keys and values are used to create the named exports of the mock module. If the mock is a CommonJS or builtin module, these values are copied ontomodule.exports
. Therefore, if a mock is created with both named exports and a non-object default export, the mock will throw an exception when used as a CJS or builtin module.
-
-
返回:<MockModuleContext> 可用于操作模拟的对象。
¥Returns: <MockModuleContext> An object that can be used to manipulate the mock.
此函数用于模拟 ECMAScript 模块、CommonJS 模块和 Node.js 内置模块的导出。模拟之前对原始模块的任何引用均不受影响。为了启用模块模拟,必须使用 --experimental-test-module-mocks
命令行标志启动 Node.js。
¥This function is used to mock the exports of ECMAScript modules, CommonJS
modules, and Node.js builtin modules. Any references to the original module
prior to mocking are not impacted. In order to enable module mocking, Node.js must
be started with the --experimental-test-module-mocks
command-line flag.
以下示例演示了如何为模块创建模拟。
¥The following example demonstrates how a mock is created for a module.
test('mocks a builtin module in both module systems', async (t) => {
// Create a mock of 'node:readline' with a named export named 'fn', which
// does not exist in the original 'node:readline' module.
const mock = t.mock.module('node:readline', {
namedExports: { fn() { return 42; } },
});
let esmImpl = await import('node:readline');
let cjsImpl = require('node:readline');
// cursorTo() is an export of the original 'node:readline' module.
assert.strictEqual(esmImpl.cursorTo, undefined);
assert.strictEqual(cjsImpl.cursorTo, undefined);
assert.strictEqual(esmImpl.fn(), 42);
assert.strictEqual(cjsImpl.fn(), 42);
mock.restore();
// The mock is restored, so the original builtin module is returned.
esmImpl = await import('node:readline');
cjsImpl = require('node:readline');
assert.strictEqual(typeof esmImpl.cursorTo, 'function');
assert.strictEqual(typeof cjsImpl.cursorTo, 'function');
assert.strictEqual(esmImpl.fn, undefined);
assert.strictEqual(cjsImpl.fn, undefined);
});
mock.reset()
#
此函数恢复了此 MockTracker
之前创建的所有模拟的默认行为,并解除了模拟与 MockTracker
实例的关联。一旦解除关联,模拟仍然可以使用,但 MockTracker
实例不能再用于重置它们的行为或以其他方式与它们交互。
¥This function restores the default behavior of all mocks that were previously
created by this MockTracker
and disassociates the mocks from the
MockTracker
instance. Once disassociated, the mocks can still be used, but the
MockTracker
instance can no longer be used to reset their behavior or
otherwise interact with them.
每次测试完成后,都会在测试上下文的 MockTracker
上调用此函数。如果广泛使用全局 MockTracker
,建议手动调用该函数。
¥After each test completes, this function is called on the test context's
MockTracker
. If the global MockTracker
is used extensively, calling this
function manually is recommended.
mock.restoreAll()
#
此函数恢复此 MockTracker
之前创建的所有模拟的默认行为。与 mock.reset()
不同,mock.restoreAll()
不会取消模拟与 MockTracker
实例的关联。
¥This function restores the default behavior of all mocks that were previously
created by this MockTracker
. Unlike mock.reset()
, mock.restoreAll()
does
not disassociate the mocks from the MockTracker
instance.
mock.setter(object, methodName[, implementation][, options])
#
此函数是 MockTracker.method
的语法糖,options.setter
设置为 true
。
¥This function is syntax sugar for MockTracker.method
with options.setter
set to true
.
类:MockTimers
#
¥Class: MockTimers
¥Stability: 1 - Experimental
模拟定时器是软件测试中常用的一种技术,用于模拟和控制定时器(例如 setInterval
和 setTimeout
)的行为,而无需实际等待指定的时间间隔。
¥Mocking timers is a technique commonly used in software testing to simulate and
control the behavior of timers, such as setInterval
and setTimeout
,
without actually waiting for the specified time intervals.
MockTimers 还能够模拟 Date
对象。
¥MockTimers is also able to mock the Date
object.
MockTracker
提供顶层 timers
导出,它是 MockTimers
实例。
¥The MockTracker
provides a top-level timers
export
which is a MockTimers
instance.
timers.enable([enableOptions])
#
启用指定定时器的定时器模拟。
¥Enables timer mocking for the specified timers.
-
enableOptions
<Object> 用于启用定时器模拟的可选配置选项。支持以下属性:¥
enableOptions
<Object> Optional configuration options for enabling timer mocking. The following properties are supported:-
apis
<Array> 包含要模拟的定时器的可选数组。当前支持的定时器值为'setInterval'
、'setTimeout'
、'setImmediate'
和'Date'
。默认值:['setInterval', 'setTimeout', 'setImmediate', 'Date']
。如果没有提供数组,则默认模拟所有时间相关的 API('setInterval'
、'clearInterval'
、'setTimeout'
、'clearTimeout'
、'setImmediate'
、'clearImmediate'
和'Date'
)。¥
apis
<Array> An optional array containing the timers to mock. The currently supported timer values are'setInterval'
,'setTimeout'
,'setImmediate'
, and'Date'
. Default:['setInterval', 'setTimeout', 'setImmediate', 'Date']
. If no array is provided, all time related APIs ('setInterval'
,'clearInterval'
,'setTimeout'
,'clearTimeout'
,'setImmediate'
,'clearImmediate'
, and'Date'
) will be mocked by default. -
now
<number> | <Date> 表示用作Date.now()
值的初始时间(以毫秒为单位)的可选数字或日期对象。默认值:0
。¥
now
<number> | <Date> An optional number or Date object representing the initial time (in milliseconds) to use as the value forDate.now()
. Default:0
.
-
注意:当你为特定定时器启用模拟时,其关联的清除函数也将被隐式模拟。
¥Note: When you enable mocking for a specific timer, its associated clear function will also be implicitly mocked.
注意:模拟 Date
将影响模拟定时器的行为,因为它们使用相同的内部时钟。
¥Note: Mocking Date
will affect the behavior of the mocked timers
as they use the same internal clock.
不设置初始时间的示例用法:
¥Example usage without setting initial time:
import { mock } from 'node:test';
mock.timers.enable({ apis: ['setInterval'] });
const { mock } = require('node:test');
mock.timers.enable({ apis: ['setInterval'] });
上面的示例启用了对 setInterval
定时器的模拟,并隐式模拟了 clearInterval
函数。仅 node:timers、node:timers/promises 和 globalThis
中的 setInterval
和 clearInterval
函数将被模拟。
¥The above example enables mocking for the setInterval
timer and
implicitly mocks the clearInterval
function. Only the setInterval
and clearInterval
functions from node:timers,
node:timers/promises, and
globalThis
will be mocked.
设置初始时间的示例用法
¥Example usage with initial time set
import { mock } from 'node:test';
mock.timers.enable({ apis: ['Date'], now: 1000 });
const { mock } = require('node:test');
mock.timers.enable({ apis: ['Date'], now: 1000 });
将初始 Date 对象设置为时间的示例用法
¥Example usage with initial Date object as time set
import { mock } from 'node:test';
mock.timers.enable({ apis: ['Date'], now: new Date() });
const { mock } = require('node:test');
mock.timers.enable({ apis: ['Date'], now: new Date() });
或者,如果你调用 mock.timers.enable()
时不带任何参数:
¥Alternatively, if you call mock.timers.enable()
without any parameters:
所有计时器('setInterval'
、'clearInterval'
、'setTimeout'
、'clearTimeout'
、'setImmediate'
和 'clearImmediate'
)都将被模拟。node:timers
、node:timers/promises
和 globalThis
中的 setInterval
、clearInterval
、setTimeout
、clearTimeout
、setImmediate
和 clearImmediate
函数将被模拟。以及全局 Date
对象。
¥All timers ('setInterval'
, 'clearInterval'
, 'setTimeout'
, 'clearTimeout'
,
'setImmediate'
, and 'clearImmediate'
) will be mocked. The setInterval
,
clearInterval
, setTimeout
, clearTimeout
, setImmediate
, and
clearImmediate
functions from node:timers
, node:timers/promises
, and
globalThis
will be mocked. As well as the global Date
object.
timers.reset()
#
此函数恢复此 MockTimers
实例之前创建的所有模拟的默认行为,并取消这些模拟与 MockTracker
实例的关联。
¥This function restores the default behavior of all mocks that were previously
created by this MockTimers
instance and disassociates the mocks
from the MockTracker
instance.
注意:每次测试完成后,都会在测试上下文的 MockTracker
上调用此函数。
¥Note: After each test completes, this function is called on
the test context's MockTracker
.
import { mock } from 'node:test';
mock.timers.reset();
const { mock } = require('node:test');
mock.timers.reset();
timers[Symbol.dispose]()
#
调用 timers.reset()
。
¥Calls timers.reset()
.
timers.tick([milliseconds])
#
提前所有模拟定时器的时间。
¥Advances time for all mocked timers.
-
milliseconds
<number> 定时器提前的时间量(以毫秒为单位)。默认值:1
。¥
milliseconds
<number> The amount of time, in milliseconds, to advance the timers. Default:1
.
注意:这与 Node.js 中 setTimeout
的行为不同,它只接受正数。在 Node.js 中,仅出于 Web 兼容性原因才支持带有负数的 setTimeout
。
¥Note: This diverges from how setTimeout
in Node.js behaves and accepts
only positive numbers. In Node.js, setTimeout
with negative numbers is
only supported for web compatibility reasons.
以下示例模拟 setTimeout
函数,并通过使用 .tick
时间提前来触发所有挂起的定时器。
¥The following example mocks a setTimeout
function and
by using .tick
advances in
time triggering all pending timers.
import assert from '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({ apis: ['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({ apis: ['setTimeout'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
// Advance in time
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
});
或者,可以多次调用 .tick
函数
¥Alternatively, the .tick
function can be called many times
import assert from '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({ apis: ['setTimeout'] });
const nineSecs = 9000;
setTimeout(fn, nineSecs);
const threeSeconds = 3000;
context.mock.timers.tick(threeSeconds);
context.mock.timers.tick(threeSeconds);
context.mock.timers.tick(threeSeconds);
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({ apis: ['setTimeout'] });
const nineSecs = 9000;
setTimeout(fn, nineSecs);
const threeSeconds = 3000;
context.mock.timers.tick(threeSeconds);
context.mock.timers.tick(threeSeconds);
context.mock.timers.tick(threeSeconds);
assert.strictEqual(fn.mock.callCount(), 1);
});
使用 .tick
提前时间也会提前启用模拟后创建的任何 Date
对象的时间(如果 Date
也设置为模拟)。
¥Advancing time using .tick
will also advance the time for any Date
object
created after the mock was enabled (if Date
was also set to be mocked).
import assert from '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({ apis: ['setTimeout', 'Date'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
assert.strictEqual(Date.now(), 0);
// Advance in time
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
assert.strictEqual(Date.now(), 9999);
});
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({ apis: ['setTimeout', 'Date'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
assert.strictEqual(Date.now(), 0);
// Advance in time
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
assert.strictEqual(Date.now(), 9999);
});
使用明确的函数#
¥Using clear functions
如上所述,计时器(clearTimeout
、clearInterval
和 clearImmediate
)的所有清除函数均被隐式模拟。看一下使用 setTimeout
的示例:
¥As mentioned, all clear functions from timers (clearTimeout
, clearInterval
,and
clearImmediate
) are implicitly mocked. Take a look at this example using setTimeout
:
import assert from '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({ apis: ['setTimeout'] });
const id = setTimeout(fn, 9999);
// Implicitly mocked as well
clearTimeout(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({ apis: ['setTimeout'] });
const id = setTimeout(fn, 9999);
// Implicitly mocked as well
clearTimeout(id);
context.mock.timers.tick(9999);
// As that setTimeout was cleared the mock function will never be called
assert.strictEqual(fn.mock.callCount(), 0);
});
使用 Node.js 定时器模块#
¥Working with Node.js timers modules
启用模拟定时器后,就会启用 Node.js 全局上下文中的 node:timers、node:timers/promises 模块和定时器:
¥Once you enable mocking timers, node:timers, node:timers/promises modules, and timers from the Node.js global context are enabled:
注意:该 API 目前不支持 import { setTimeout } from 'node:timers'
等解构函数。
¥Note: Destructuring functions such as
import { setTimeout } from 'node:timers'
is currently
not supported by this API.
import assert from 'node:assert';
import { test } from 'node:test';
import nodeTimers from 'node:timers';
import nodeTimersPromises from '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({ apis: ['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({ apis: ['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);
});
在 Node.js 中,node:timers/promises 中的 setInterval
是 AsyncGenerator
,并且也受此 API 支持:
¥In Node.js, setInterval
from node:timers/promises
is an AsyncGenerator
and is also supported by this API:
import assert from 'node:assert';
import { test } from 'node:test';
import nodeTimersPromises from 'node:timers/promises';
test('should tick five times testing a real use case', async (context) => {
context.mock.timers.enable({ apis: ['setInterval'] });
const expectedIterations = 3;
const interval = 1000;
const startedAt = Date.now();
async function run() {
const times = [];
for await (const time of 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({ apis: ['setInterval'] });
const expectedIterations = 3;
const interval = 1000;
const startedAt = Date.now();
async function run() {
const times = [];
for await (const time of 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()
#
立即触发所有待处理的模拟定时器。如果 Date
对象也被模拟,它也会将 Date
对象提前到最远的定时器时间。
¥Triggers all pending mocked timers immediately. If the Date
object is also
mocked, it will also advance the Date
object to the furthest timer's time.
下面的示例立即触发所有待处理的定时器,使它们立即执行。
¥The example below triggers all pending timers immediately, causing them to execute without any delay.
import assert from 'node:assert';
import { test } from 'node:test';
test('runAll functions following the given order', (context) => {
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const results = [];
setTimeout(() => results.push(1), 9999);
// Notice that if both timers have the same timeout,
// the order of execution is guaranteed
setTimeout(() => results.push(3), 8888);
setTimeout(() => results.push(2), 8888);
assert.deepStrictEqual(results, []);
context.mock.timers.runAll();
assert.deepStrictEqual(results, [3, 2, 1]);
// The Date object is also advanced to the furthest timer's time
assert.strictEqual(Date.now(), 9999);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('runAll functions following the given order', (context) => {
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const results = [];
setTimeout(() => results.push(1), 9999);
// Notice that if both timers have the same timeout,
// the order of execution is guaranteed
setTimeout(() => results.push(3), 8888);
setTimeout(() => results.push(2), 8888);
assert.deepStrictEqual(results, []);
context.mock.timers.runAll();
assert.deepStrictEqual(results, [3, 2, 1]);
// The Date object is also advanced to the furthest timer's time
assert.strictEqual(Date.now(), 9999);
});
注意:runAll()
函数是专门为在定时器模拟上下文中触发定时器而设计的。它对模拟环境之外的实时系统时钟或实际定时器没有任何影响。
¥Note: The runAll()
function is specifically designed for
triggering timers in the context of timer mocking.
It does not have any effect on real-time system
clocks or actual timers outside of the mocking environment.
timers.setTime(milliseconds)
#
设置当前 Unix 时间戳,该时间戳将用作任何模拟 Date
对象的参考。
¥Sets the current Unix timestamp that will be used as reference for any mocked
Date
objects.
import assert from 'node:assert';
import { test } from 'node:test';
test('runAll functions following the given order', (context) => {
const now = Date.now();
const setTime = 1000;
// Date.now is not mocked
assert.deepStrictEqual(Date.now(), now);
context.mock.timers.enable({ apis: ['Date'] });
context.mock.timers.setTime(setTime);
// Date.now is now 1000
assert.strictEqual(Date.now(), setTime);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('setTime replaces current time', (context) => {
const now = Date.now();
const setTime = 1000;
// Date.now is not mocked
assert.deepStrictEqual(Date.now(), now);
context.mock.timers.enable({ apis: ['Date'] });
context.mock.timers.setTime(setTime);
// Date.now is now 1000
assert.strictEqual(Date.now(), setTime);
});
日期和定时器一起工作#
¥Dates and Timers working together
日期和定时器对象相互依赖。如果使用 setTime()
将当前时间传递给模拟的 Date
对象,则使用 setTimeout
和 setInterval
设置的定时器不会受到影响。
¥Dates and timer objects are dependent on each other. If you use setTime()
to
pass the current time to the mocked Date
object, the set timers with
setTimeout
and setInterval
will not be affected.
但是,tick
方法将推进模拟的 Date
对象。
¥However, the tick
method will advanced the mocked Date
object.
import assert from 'node:assert';
import { test } from 'node:test';
test('runAll functions following the given order', (context) => {
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const results = [];
setTimeout(() => results.push(1), 9999);
assert.deepStrictEqual(results, []);
context.mock.timers.setTime(12000);
assert.deepStrictEqual(results, []);
// The date is advanced but the timers don't tick
assert.strictEqual(Date.now(), 12000);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('runAll functions following the given order', (context) => {
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const results = [];
setTimeout(() => results.push(1), 9999);
assert.deepStrictEqual(results, []);
context.mock.timers.setTime(12000);
assert.deepStrictEqual(results, []);
// The date is advanced but the timers don't tick
assert.strictEqual(Date.now(), 12000);
});
类:TestsStream
#
¥Class: TestsStream
-
延长 <Readable>
¥Extends <Readable>
成功调用 run()
方法将返回一个新的 <TestsStream> 对象,流式传输代表测试执行的一系列事件。TestsStream
将按照测试定义的顺序触发事件
¥A successful call to run()
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
某些事件保证按照测试定义的顺序触发,而其他事件则按照测试执行的顺序触发。
¥Some of the events are guaranteed to be emitted in the same order as the tests are defined, while others are emitted in the order that the tests execute.
事件:'test:coverage'
#
¥Event: 'test:coverage'
-
data
<Object>-
summary
<Object> 包含覆盖率报告的对象。¥
summary
<Object> An object containing the coverage report.-
files
<Array> 单个文件的一系列覆盖率报告。每个报告都是具有以下架构的对象:¥
files
<Array> An array of coverage reports for individual files. Each report is an object with the following schema:-
path
<string> 文件的绝对路径。¥
path
<string> The absolute path of the file. -
totalLineCount
<number> 总行数。¥
totalLineCount
<number> The total number of lines. -
totalBranchCount
<number> 分支总数。¥
totalBranchCount
<number> The total number of branches. -
totalFunctionCount
<number> 函数总数。¥
totalFunctionCount
<number> The total number of functions. -
coveredLineCount
<number> 被覆盖的行数。¥
coveredLineCount
<number> The number of covered lines. -
coveredBranchCount
<number> 覆盖的分支数。¥
coveredBranchCount
<number> The number of covered branches. -
coveredFunctionCount
<number> 覆盖函数的个数。¥
coveredFunctionCount
<number> The number of covered functions. -
coveredLinePercent
<number> 覆盖行的百分比。¥
coveredLinePercent
<number> The percentage of lines covered. -
coveredBranchPercent
<number> 覆盖的分支百分比。¥
coveredBranchPercent
<number> The percentage of branches covered. -
coveredFunctionPercent
<number> 覆盖的函数百分比。¥
coveredFunctionPercent
<number> The percentage of functions covered. -
functions
<Array> 表示函数覆盖率的函数数组。¥
functions
<Array> An array of functions representing function coverage. -
branches
<Array> 代表分支覆盖范围的分支数组。¥
branches
<Array> An array of branches representing branch coverage. -
lines
<Array> 表示行号及其被覆盖次数的行数组。¥
lines
<Array> An array of lines representing line numbers and the number of times they were covered.
-
-
thresholds
<Object> 包含每种覆盖类型是否覆盖的对象。¥
thresholds
<Object> An object containing whether or not the coverage for each coverage type. -
totals
<Object> 包含所有文件覆盖率摘要的对象。¥
totals
<Object> An object containing a summary of coverage for all files.-
totalLineCount
<number> 总行数。¥
totalLineCount
<number> The total number of lines. -
totalBranchCount
<number> 分支总数。¥
totalBranchCount
<number> The total number of branches. -
totalFunctionCount
<number> 函数总数。¥
totalFunctionCount
<number> The total number of functions. -
coveredLineCount
<number> 被覆盖的行数。¥
coveredLineCount
<number> The number of covered lines. -
coveredBranchCount
<number> 覆盖的分支数。¥
coveredBranchCount
<number> The number of covered branches. -
coveredFunctionCount
<number> 覆盖函数的个数。¥
coveredFunctionCount
<number> The number of covered functions. -
coveredLinePercent
<number> 覆盖行的百分比。¥
coveredLinePercent
<number> The percentage of lines covered. -
coveredBranchPercent
<number> 覆盖的分支百分比。¥
coveredBranchPercent
<number> The percentage of branches covered. -
coveredFunctionPercent
<number> 覆盖的函数百分比。¥
coveredFunctionPercent
<number> The percentage of functions covered.
-
-
workingDirectory
<string> 代码覆盖开始时的工作目录。这对于显示相对路径名很有用,以防测试更改了 Node.js 进程的工作目录。¥
workingDirectory
<string> The working directory when code coverage began. This is useful for displaying relative path names in case the tests changed the working directory of the Node.js process.
-
-
nesting
<number> 测试的嵌套级别。¥
nesting
<number> The nesting level of the test.
-
启用代码覆盖率并且所有测试都已完成时触发。
¥Emitted when code coverage is enabled and all tests have completed.
事件:'test:complete'
#
¥Event: 'test:complete'
-
data
<Object>-
column
<number> | <undefined> 定义测试的列号,如果测试是通过 REPL 运行的,则为undefined
。¥
column
<number> | <undefined> The column number where the test is defined, orundefined
if the test was run through the REPL. -
details
<Object> 额外的执行元数据。¥
details
<Object> Additional execution metadata.-
passed
<boolean> 测试是否通过。¥
passed
<boolean> Whether the test passed or not. -
duration_ms
<number> 以毫秒为单位的测试持续时间。¥
duration_ms
<number> The duration of the test in milliseconds. -
error
<Error> | <undefined> 如果测试未通过,则封装测试抛出的错误。¥
error
<Error> | <undefined> An error wrapping the error thrown by the test if it did not pass. -
type
<string> | <undefined> 测试的类型,用于指示这是否是一个套件。¥
type
<string> | <undefined> The type of the test, used to denote whether this is a suite.
-
-
file
<string> | <undefined> 测试文件的路径,如果测试是通过 REPL 运行的,则为undefined
。¥
file
<string> | <undefined> The path of the test file,undefined
if test was run through the REPL. -
line
<number> | <undefined> 定义测试的行号,如果测试是通过 REPL 运行的,则为undefined
。¥
line
<number> | <undefined> The line number where the test is defined, orundefined
if the test was run through the REPL. -
name
<string> 测试名称。¥
name
<string> The test name. -
nesting
<number> 测试的嵌套级别。¥
nesting
<number> The nesting level of the test. -
testNumber
<number> 测试的序号。¥
testNumber
<number> The ordinal number of the test. -
todo
<string> | <boolean> | <undefined> 如果调用context.todo
,则存在¥
todo
<string> | <boolean> | <undefined> Present ifcontext.todo
is called -
skip
<string> | <boolean> | <undefined> 如果调用context.skip
,则存在¥
skip
<string> | <boolean> | <undefined> Present ifcontext.skip
is called
-
当测试完成执行时触发。此事件的触发顺序与测试定义的顺序不同。对应的声明有序事件是 'test:pass'
和 'test:fail'
。
¥Emitted when a test completes its execution.
This event is not emitted in the same order as the tests are
defined.
The corresponding declaration ordered events are 'test:pass'
and 'test:fail'
.
事件:'test:dequeue'
#
¥Event: 'test:dequeue'
-
data
<Object>-
column
<number> | <undefined> 定义测试的列号,如果测试是通过 REPL 运行的,则为undefined
。¥
column
<number> | <undefined> The column number where the test is defined, orundefined
if the test was run through the REPL. -
file
<string> | <undefined> 测试文件的路径,如果测试是通过 REPL 运行的,则为undefined
。¥
file
<string> | <undefined> The path of the test file,undefined
if test was run through the REPL. -
line
<number> | <undefined> 定义测试的行号,如果测试是通过 REPL 运行的,则为undefined
。¥
line
<number> | <undefined> The line number where the test is defined, orundefined
if the test was run through the REPL. -
name
<string> 测试名称。¥
name
<string> The test name. -
nesting
<number> 测试的嵌套级别。¥
nesting
<number> The nesting level of the test.
-
当测试出列时(在执行之前)触发。不保证此事件按照测试定义的顺序触发。对应的声明顺序事件为 'test:start'
。
¥Emitted when a test is dequeued, right before it is executed.
This event is not guaranteed to be emitted in the same order as the tests are
defined. The corresponding declaration ordered event is 'test:start'
.
事件:'test:diagnostic'
#
¥Event: 'test:diagnostic'
-
data
<Object>-
column
<number> | <undefined> 定义测试的列号,如果测试是通过 REPL 运行的,则为undefined
。¥
column
<number> | <undefined> The column number where the test is defined, orundefined
if the test was run through the REPL. -
file
<string> | <undefined> 测试文件的路径,如果测试是通过 REPL 运行的,则为undefined
。¥
file
<string> | <undefined> The path of the test file,undefined
if test was run through the REPL. -
line
<number> | <undefined> 定义测试的行号,如果测试是通过 REPL 运行的,则为undefined
。¥
line
<number> | <undefined> The line number where the test is defined, orundefined
if the test was run through the REPL. -
message
<string> 诊断消息。¥
message
<string> The diagnostic message. -
nesting
<number> 测试的嵌套级别。¥
nesting
<number> The nesting level of the test.
-
调用 context.diagnostic
时触发。该事件保证按照测试定义的顺序触发。
¥Emitted when context.diagnostic
is called.
This event is guaranteed to be emitted in the same order as the tests are
defined.
事件:'test:enqueue'
#
¥Event: 'test:enqueue'
-
data
<Object>-
column
<number> | <undefined> 定义测试的列号,如果测试是通过 REPL 运行的,则为undefined
。¥
column
<number> | <undefined> The column number where the test is defined, orundefined
if the test was run through the REPL. -
file
<string> | <undefined> 测试文件的路径,如果测试是通过 REPL 运行的,则为undefined
。¥
file
<string> | <undefined> The path of the test file,undefined
if test was run through the REPL. -
line
<number> | <undefined> 定义测试的行号,如果测试是通过 REPL 运行的,则为undefined
。¥
line
<number> | <undefined> The line number where the test is defined, orundefined
if the test was run through the REPL. -
name
<string> 测试名称。¥
name
<string> The test name. -
nesting
<number> 测试的嵌套级别。¥
nesting
<number> The nesting level of the test.
-
当测试排队执行时触发。
¥Emitted when a test is enqueued for execution.
事件:'test:fail'
#
¥Event: 'test:fail'
-
data
<Object>-
column
<number> | <undefined> 定义测试的列号,如果测试是通过 REPL 运行的,则为undefined
。¥
column
<number> | <undefined> The column number where the test is defined, orundefined
if the test was run through the REPL. -
details
<Object> 额外的执行元数据。¥
details
<Object> Additional execution metadata.-
duration_ms
<number> 以毫秒为单位的测试持续时间。¥
duration_ms
<number> The duration of the test in milliseconds. -
error
<Error> 封装测试引发的错误的错误。¥
error
<Error> An error wrapping the error thrown by the test. -
type
<string> | <undefined> 测试的类型,用于指示这是否是一个套件。¥
type
<string> | <undefined> The type of the test, used to denote whether this is a suite.
-
-
file
<string> | <undefined> 测试文件的路径,如果测试是通过 REPL 运行的,则为undefined
。¥
file
<string> | <undefined> The path of the test file,undefined
if test was run through the REPL. -
line
<number> | <undefined> 定义测试的行号,如果测试是通过 REPL 运行的,则为undefined
。¥
line
<number> | <undefined> The line number where the test is defined, orundefined
if the test was run through the REPL. -
name
<string> 测试名称。¥
name
<string> The test name. -
nesting
<number> 测试的嵌套级别。¥
nesting
<number> The nesting level of the test. -
testNumber
<number> 测试的序号。¥
testNumber
<number> The ordinal number of the test. -
todo
<string> | <boolean> | <undefined> 如果调用context.todo
,则存在¥
todo
<string> | <boolean> | <undefined> Present ifcontext.todo
is called -
skip
<string> | <boolean> | <undefined> 如果调用context.skip
,则存在¥
skip
<string> | <boolean> | <undefined> Present ifcontext.skip
is called
-
测试失败时触发。该事件保证按照测试定义的顺序触发。对应的执行命令事件为 'test:complete'
。
¥Emitted when a test fails.
This event is guaranteed to be emitted in the same order as the tests are
defined.
The corresponding execution ordered event is 'test:complete'
.
事件:'test:pass'
#
¥Event: 'test:pass'
-
data
<Object>-
column
<number> | <undefined> 定义测试的列号,如果测试是通过 REPL 运行的,则为undefined
。¥
column
<number> | <undefined> The column number where the test is defined, orundefined
if the test was run through the REPL. -
details
<Object> 额外的执行元数据。¥
details
<Object> Additional execution metadata.-
duration_ms
<number> 以毫秒为单位的测试持续时间。¥
duration_ms
<number> The duration of the test in milliseconds. -
type
<string> | <undefined> 测试的类型,用于指示这是否是一个套件。¥
type
<string> | <undefined> The type of the test, used to denote whether this is a suite.
-
-
file
<string> | <undefined> 测试文件的路径,如果测试是通过 REPL 运行的,则为undefined
。¥
file
<string> | <undefined> The path of the test file,undefined
if test was run through the REPL. -
line
<number> | <undefined> 定义测试的行号,如果测试是通过 REPL 运行的,则为undefined
。¥
line
<number> | <undefined> The line number where the test is defined, orundefined
if the test was run through the REPL. -
name
<string> 测试名称。¥
name
<string> The test name. -
nesting
<number> 测试的嵌套级别。¥
nesting
<number> The nesting level of the test. -
testNumber
<number> 测试的序号。¥
testNumber
<number> The ordinal number of the test. -
todo
<string> | <boolean> | <undefined> 如果调用context.todo
,则存在¥
todo
<string> | <boolean> | <undefined> Present ifcontext.todo
is called -
skip
<string> | <boolean> | <undefined> 如果调用context.skip
,则存在¥
skip
<string> | <boolean> | <undefined> Present ifcontext.skip
is called
-
测试通过时触发。该事件保证按照测试定义的顺序触发。对应的执行命令事件为 'test:complete'
。
¥Emitted when a test passes.
This event is guaranteed to be emitted in the same order as the tests are
defined.
The corresponding execution ordered event is 'test:complete'
.
事件:'test:plan'
#
¥Event: 'test:plan'
-
data
<Object>-
column
<number> | <undefined> 定义测试的列号,如果测试是通过 REPL 运行的,则为undefined
。¥
column
<number> | <undefined> The column number where the test is defined, orundefined
if the test was run through the REPL. -
file
<string> | <undefined> 测试文件的路径,如果测试是通过 REPL 运行的,则为undefined
。¥
file
<string> | <undefined> The path of the test file,undefined
if test was run through the REPL. -
line
<number> | <undefined> 定义测试的行号,如果测试是通过 REPL 运行的,则为undefined
。¥
line
<number> | <undefined> The line number where the test is defined, orundefined
if the test was run through the REPL. -
nesting
<number> 测试的嵌套级别。¥
nesting
<number> The nesting level of the test. -
count
<number> 已运行的子测试数。¥
count
<number> The number of subtests that have ran.
-
当给定测试的所有子测试都完成时触发。该事件保证按照测试定义的顺序触发。
¥Emitted when all subtests have completed for a given test. This event is guaranteed to be emitted in the same order as the tests are defined.
事件:'test:start'
#
¥Event: 'test:start'
-
data
<Object>-
column
<number> | <undefined> 定义测试的列号,如果测试是通过 REPL 运行的,则为undefined
。¥
column
<number> | <undefined> The column number where the test is defined, orundefined
if the test was run through the REPL. -
file
<string> | <undefined> 测试文件的路径,如果测试是通过 REPL 运行的,则为undefined
。¥
file
<string> | <undefined> The path of the test file,undefined
if test was run through the REPL. -
line
<number> | <undefined> 定义测试的行号,如果测试是通过 REPL 运行的,则为undefined
。¥
line
<number> | <undefined> The line number where the test is defined, orundefined
if the test was run through the REPL. -
name
<string> 测试名称。¥
name
<string> The test name. -
nesting
<number> 测试的嵌套级别。¥
nesting
<number> The nesting level of the test.
-
当测试开始报告其自身及其子测试状态时触发。该事件保证按照测试定义的顺序触发。对应的执行命令事件为 'test:dequeue'
。
¥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 are
defined.
The corresponding execution ordered event is 'test:dequeue'
.
事件:'test:stderr'
#
¥Event: 'test:stderr'
-
data
<Object>
当正在运行的测试写入 stderr
时触发。只有在传递 --test
标志时才会触发此事件。不保证此事件按照测试定义的顺序触发。
¥Emitted when a running test writes to stderr
.
This event is only emitted if --test
flag is passed.
This event is not guaranteed to be emitted in the same order as the tests are
defined.
事件:'test:stdout'
#
¥Event: 'test:stdout'
-
data
<Object>
当正在运行的测试写入 stdout
时触发。只有在传递 --test
标志时才会触发此事件。不保证此事件按照测试定义的顺序触发。
¥Emitted when a running test writes to stdout
.
This event is only emitted if --test
flag is passed.
This event is not guaranteed to be emitted in the same order as the tests are
defined.
事件:'test:summary'
#
¥Event: 'test:summary'
-
data
<Object>-
counts
<Object> 包含各种测试结果计数的对象。¥
counts
<Object> An object containing the counts of various test results.-
cancelled
<number> 取消的测试总数。¥
cancelled
<number> The total number of cancelled tests. -
failed
<number> 失败的测试总数。¥
failed
<number> The total number of failed tests. -
passed
<number> 通过的测试总数。¥
passed
<number> The total number of passed tests. -
skipped
<number> 跳过的测试总数。¥
skipped
<number> The total number of skipped tests. -
suites
<number> 运行的套件总数。¥
suites
<number> The total number of suites run. -
tests
<number> 运行的测试总数,不包括套件。¥
tests
<number> The total number of tests run, excluding suites. -
todo
<number> TODO 测试的总数。¥
todo
<number> The total number of TODO tests. -
topLevel
<number> 顶层测试和套件的总数。¥
topLevel
<number> The total number of top level tests and suites.
-
-
duration_ms
<number> 测试运行的持续时间(以毫秒为单位)。¥
duration_ms
<number> The duration of the test run in milliseconds. -
file
<string> | <undefined> 生成摘要的测试文件的路径。如果摘要对应多个文件,则此值为undefined
。¥
file
<string> | <undefined> The path of the test file that generated the summary. If the summary corresponds to multiple files, this value isundefined
. -
success
<boolean> 表示测试运行是否成功。如果发生任何错误情况,例如测试失败或未达到覆盖率阈值,则此值将设置为false
。¥
success
<boolean> Indicates whether or not the test run is considered successful or not. If any error condition occurs, such as a failing test or unmet coverage threshold, this value will be set tofalse
.
-
测试运行完成时触发。此事件包含与已完成的测试运行有关的指标,可用于确定测试运行是通过还是失败。如果使用流程级测试隔离,除了最终累积摘要之外,还会为每个测试文件生成一个 'test:summary'
事件。
¥Emitted when a test run completes. This event contains metrics pertaining to
the completed test run, and is useful for determining if a test run passed or
failed. If process-level test isolation is used, a 'test:summary'
event is
generated for each test file in addition to a final cumulative summary.
事件:'test:watch:drained'
#
¥Event: 'test:watch:drained'
当没有更多测试排队等待以监视模式执行时触发。
¥Emitted when no more tests are queued for execution in watch mode.
类:TestContext
#
¥Class: TestContext
TestContext
的实例被传给每个测试函数,以便与测试运行器交互。但是,TestContext
构造函数没有作为 API 的一部分公开。
¥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])
#
-
fn
<Function> | <AsyncFunction> 钩子函数。此函数的第一个参数是TestContext
对象。如果钩子使用回调,则回调函数作为第二个参数传入。默认值:空操作函数。¥
fn
<Function> | <AsyncFunction> The hook function. The first argument to this function is aTestContext
object. If the hook uses callbacks, the callback function is passed as the second argument. Default: A no-op function. -
options
<Object> 钩子的配置选项。支持以下属性:¥
options
<Object> Configuration options for the hook. The following properties are supported:-
signal
<AbortSignal> 允许中止正在进行的钩子。¥
signal
<AbortSignal> Allows aborting an in-progress hook. -
timeout
<number> 钩子会在几毫秒后失败。如果未指定,则子测试从其父测试继承此值。默认值:Infinity
。¥
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 subtest of the current test.
context.beforeEach([fn][, options])
#
-
fn
<Function> | <AsyncFunction> 钩子函数。此函数的第一个参数是TestContext
对象。如果钩子使用回调,则回调函数作为第二个参数传入。默认值:空操作函数。¥
fn
<Function> | <AsyncFunction> The hook function. The first argument to this function is aTestContext
object. If the hook uses callbacks, the callback function is passed as the second argument. Default: A no-op function. -
options
<Object> 钩子的配置选项。支持以下属性:¥
options
<Object> Configuration options for the hook. The following properties are supported:-
signal
<AbortSignal> 允许中止正在进行的钩子。¥
signal
<AbortSignal> Allows aborting an in-progress hook. -
timeout
<number> 钩子会在几毫秒后失败。如果未指定,则子测试从其父测试继承此值。默认值:Infinity
。¥
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 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> 钩子函数。此函数的第一个参数是TestContext
对象。如果钩子使用回调,则回调函数作为第二个参数传入。默认值:空操作函数。¥
fn
<Function> | <AsyncFunction> The hook function. The first argument to this function is aTestContext
object. If the hook uses callbacks, the callback function is passed as the second argument. Default: A no-op function. -
options
<Object> 钩子的配置选项。支持以下属性:¥
options
<Object> Configuration options for the hook. The following properties are supported:-
signal
<AbortSignal> 允许中止正在进行的钩子。¥
signal
<AbortSignal> Allows aborting an in-progress hook. -
timeout
<number> 钩子会在几毫秒后失败。如果未指定,则子测试从其父测试继承此值。默认值:Infinity
。¥
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 test finishes.
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> 钩子函数。此函数的第一个参数是TestContext
对象。如果钩子使用回调,则回调函数作为第二个参数传入。默认值:空操作函数。¥
fn
<Function> | <AsyncFunction> The hook function. The first argument to this function is aTestContext
object. If the hook uses callbacks, the callback function is passed as the second argument. Default: A no-op function. -
options
<Object> 钩子的配置选项。支持以下属性:¥
options
<Object> Configuration options for the hook. The following properties are supported:-
signal
<AbortSignal> 允许中止正在进行的钩子。¥
signal
<AbortSignal> Allows aborting an in-progress hook. -
timeout
<number> 钩子会在几毫秒后失败。如果未指定,则子测试从其父测试继承此值。默认值:Infinity
。¥
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 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.assert
#
包含绑定到 context
的断言方法的对象。这里公开了 node:assert
模块的顶层函数,用于创建测试计划。
¥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.snapshot(value[, options])
#
¥Stability: 1.0 - Early development
-
value
<any> 要序列化为字符串的值。如果 Node.js 是使用--test-update-snapshots
标志启动的,则序列化值将写入快照文件。否则,序列化值将与现有快照文件中的相应值进行比较。¥
value
<any> A value to serialize to a string. If Node.js was started with the--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. -
options
<Object> 可选配置选项。支持以下属性:¥
options
<Object> Optional configuration options. The following properties are supported:-
serializers
<Array> 用于将value
序列化为字符串的同步函数数组。value
作为第一个序列化器函数的唯一参数传递。每个序列化器的返回值作为输入传递给下一个序列化器。一旦所有序列化器都运行完毕,结果值就会被强制转换为字符串。默认值:如果没有提供序列化器,则使用测试运行器的默认序列化器。¥
serializers
<Array> An array of synchronous functions used to serializevalue
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)
#
此函数用于将诊断写入输出。任何诊断信息都包含在测试结果的末尾。此函数不返回值。
¥This 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.filePath
#
创建当前测试的测试文件的绝对路径。如果测试文件导入了生成测试的其他模块,则导入的测试将返回根测试文件的路径。
¥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.
context.fullName
#
测试的名称及其每个祖级,以 >
分隔。
¥The name of the test and each of its ancestors, separated by >
.
context.name
#
测试名称。
¥The name of the test.
context.plan(count)
#
¥Stability: 1 - Experimental
-
count
<number> 预期运行的断言和子测试的数量。¥
count
<number> The number of assertions and subtests that are expected to run.
此函数用于设置预期在测试中运行的断言和子测试的数量。如果运行的断言和子测试的数量与预期计数不匹配,则测试将失败。
¥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.
注意:为了确保跟踪断言,必须直接使用
t.assert
而不是assert
。¥Note: To make sure assertions are tracked,
t.assert
must be used instead ofassert
directly.
test('top level test', (t) => {
t.plan(2);
t.assert.ok('some relevant assertion here');
t.test('subtest', () => {});
});
使用异步代码时,可以使用 plan
函数来确保运行正确数量的断言:
¥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();
});
});
context.runOnly(shouldRunOnlyTests)
#
-
shouldRunOnlyTests
<boolean> 是否运行only
测试。¥
shouldRunOnlyTests
<boolean> Whether or not to runonly
tests.
如果 shouldRunOnlyTests
为真,则测试上下文将只运行设置了 only
选项的测试。否则,将运行所有测试。如果 Node.js 不是使用 --test-only
命令行选项启动的,则此函数是无操作的。
¥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 }),
]);
});
context.signal
#
-
¥Type: <AbortSignal>
可用于在测试中止时中止测试子任务。
¥Can 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])
#
此函数使测试的输出指示测试已跳过。如果提供了 message
,它会包含在输出中。调用 skip()
不会终止测试函数的执行。此函数不返回值。
¥This 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])
#
此函数将 TODO
指令添加到测试的输出中。如果提供了 message
,它会包含在输出中。调用 todo()
不会终止测试函数的执行。此函数不返回值。
¥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([name][, options][, fn])
#
-
name
<string> 子测试的名称,在报告测试结果时显示。默认值:fn
的name
属性,如果fn
没有名称,则为'<anonymous>'
。¥
name
<string> The name of the subtest, which is displayed when reporting test results. Default: Thename
property offn
, or'<anonymous>'
iffn
does not have a name. -
options
<Object> 子测试的配置选项。支持以下属性:¥
options
<Object> Configuration options for the subtest. The following properties are supported:-
concurrency
<number> | <boolean> | <null> 如果提供了一个数字,那么许多测试将在应用线程中并行运行。如果是true
,它将并行运行所有子测试。如果是false
,它一次只会运行一个测试。如果未指定,则子测试从其父测试继承此值。默认值:null
。¥
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> 如果为真,并且测试上下文配置为运行only
测试,则将运行此测试。否则跳过测试。默认值:false
。¥
only
<boolean> If truthy, and the test context is configured to runonly
tests, then this test will be run. Otherwise, the test is skipped. Default:false
. -
signal
<AbortSignal> 允许中止正在进行的测试。¥
signal
<AbortSignal> Allows aborting an in-progress test. -
skip
<boolean> | <string> 如果为真,则跳过测试。如果提供了字符串,则该字符串将作为跳过测试的原因显示在测试结果中。默认值:false
。¥
skip
<boolean> | <string> If truthy, the test is skipped. If a string is provided, that string is displayed in the test results as the reason for skipping the test. Default:false
. -
todo
<boolean> | <string> 如果为真,则测试标记为TODO
。如果提供了字符串,则该字符串会显示在测试结果中作为测试为TODO
的原因。默认值:false
。¥
todo
<boolean> | <string> If truthy, the test marked asTODO
. If a string is provided, that string is displayed in the test results as the reason why the test isTODO
. Default:false
. -
timeout
<number> 测试失败的毫秒数。如果未指定,则子测试从其父测试继承此值。默认值:Infinity
。¥
timeout
<number> A number of milliseconds the test will fail after. If unspecified, subtests inherit this value from their parent. Default:Infinity
. -
plan
<number> 预期在测试中运行的断言和子测试的数量。如果测试中运行的断言数量与计划中指定的数量不匹配,则测试将失败。默认值:undefined
。¥
plan
<number> The number of assertions and subtests expected to be run in the test. If the number of assertions run in the test does not match the number specified in the plan, the test will fail. Default:undefined
.
-
-
fn
<Function> | <AsyncFunction> 被测试的函数。此函数的第一个参数是TestContext
对象。如果测试使用回调,则回调函数作为第二个参数传入。默认值:空操作函数。¥
fn
<Function> | <AsyncFunction> The function under test. The first argument to this function is aTestContext
object. If the test uses callbacks, the callback function is passed as the second argument. Default: A no-op function. -
返回:<Promise> 测试完成后,满足
undefined
。¥Returns: <Promise> Fulfilled with
undefined
once the test completes.
此函数用于在当前测试下创建子测试。此函数的行为方式与顶层的 test()
函数相同。
¥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');
},
);
});
类:SuiteContext
#
¥Class: SuiteContext
SuiteContext
的实例被传给每个套件函数,以便与测试运行器进行交互。但是,SuiteContext
构造函数没有作为 API 的一部分公开。
¥An instance of SuiteContext
is passed to each suite function in order to
interact with the test runner. However, the SuiteContext
constructor is not
exposed as part of the API.
context.filePath
#
创建当前套件的测试文件的绝对路径。如果测试文件导入了生成套件的其他模块,则导入的套件将返回根测试文件的路径。
¥The absolute path of the test file that created the current suite. If a test file imports additional modules that generate suites, the imported suites will return the path of the root test file.
context.name
#
套件名称。
¥The name of the suite.
context.signal
#
-
¥Type: <AbortSignal>
可用于在测试中止时中止测试子任务。
¥Can be used to abort test subtasks when the test has been aborted.