- 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/cjsCommonJS模块
- module/esmECMAScript模块
- module/package包模块
- net网络
- os操作系统
- path路径
- perf_hooks性能钩子
- policy安全策略
- process进程
- punycode域名代码
- querystring查询字符串
- readline逐行读取
- repl交互式解释器
- report诊断报告
- stream流
- stream/web网络流
- string_decoder字符串解码器
- test测试
- timers定时器
- tls安全传输层
- trace_events跟踪事件
- tty终端
- url网址
- util实用工具
- v8引擎
- vm虚拟机
- wasi网络汇编系统接口
- worker_threads工作线程
- zlib压缩
Node.js v18.6.0 文档
- Node.js 18.6.0
- ► 目录
-
►
索引
- 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 包模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- policy 安全策略
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- stream 流
- stream/web 网络流
- string_decoder 字符串解码器
- test 测试
- timers 定时器
- tls 安全传输层
- trace_events 跟踪事件
- tty 终端
- url 网址
- util 实用工具
- v8 引擎
- vm 虚拟机
- wasi 网络汇编系统接口
- worker_threads 工作线程
- zlib 压缩
- 搜索
目录
test 测试#
源代码: lib/test.js
node:test
模块有助于创建以 TAP 格式报告结果的 JavaScript 测试。
要访问它:
import test from 'node:test';
const test = require('node:test');
此模块仅在 node:
协议下可用。
以下将不起作用:
import test from 'test';
const test = require('test');
通过 test
模块创建的测试由单个函数组成,该函数以三种方式之一进行处理:
- 同步的函数,如果抛出异常则认为失败,否则认为通过。
- 返回
Promise
的函数,如果Promise
拒绝,则认为该函数失败,如果Promise
解决,则认为该函数通过。 - 接收回调函数的函数。
如果回调接收到任何真值作为其第一个参数,则认为测试失败。
如果非真值作为第一个参数传给回调,则认为测试通过。
如果测试函数接收到回调函数并且还返回
Promise
,则测试将失败。
以下示例说明了如何使用 test
模块编写测试。
test('synchronous passing test', (t) => {
// 此测试通过了,因为它没有抛出异常。
assert.strictEqual(1, 1);
});
test('synchronous failing test', (t) => {
// 此测试失败,因为它抛出了异常。
assert.strictEqual(1, 2);
});
test('asynchronous passing test', async (t) => {
// 此测试通过了,
// 因为异步函数返回的 Promise 没有被拒绝。
assert.strictEqual(1, 1);
});
test('asynchronous failing test', async (t) => {
// 此测试失败,
// 因为异步函数返回的 Promise 被拒绝。
assert.strictEqual(1, 2);
});
test('failing test using Promises', (t) => {
// Promise 也可以直接使用。
return new Promise((resolve, reject) => {
setImmediate(() => {
reject(new Error('this will cause the test to fail'));
});
});
});
test('callback passing test', (t, done) => {
// done() 是回调函数。
// 当 setImmediate() 运行时,它调用 done() 不带参数。
setImmediate(done);
});
test('callback failing test', (t, done) => {
// 当 setImmediate() 运行时,
// 使用 Error 对象调用 done() 并且测试失败。
setImmediate(() => {
done(new Error('callback failure'));
});
});
当测试文件执行时,TAP 被写入 Node.js 进程的标准输出。
此输出可以被任何理解 TAP 格式的测试工具解释。
如果任何测试失败,则进程退出代码设置为 1
。
子测试#
测试上下文的 test()
方法允许创建子测试。
此方法的行为与顶层 test()
函数相同。
以下示例演示了如何创建具有两个子测试的顶层测试。
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);
});
});
在本示例中,await
用于确保两个子测试均已完成。
这是必要的,因为父测试不会等待子测试完成。
当父测试完成时仍然未完成的任何子测试将被取消并视为失败。
任何子测试失败都会导致父测试失败。
跳过测试#
通过将 skip
选项传给测试,或调用测试上下文的 skip()
方法,可以跳过单个测试。
这两个选项都支持包括在 TAP 输出中显示的消息,如下例所示。
// 使用了跳过选项,但没有提供任何消息。
test('skip option', { skip: true }, (t) => {
// 这段代码永远不会被执行。
});
// 使用了跳过选项,并提供了一条消息。
test('skip option with message', { skip: 'this is skipped' }, (t) => {
// 这段代码永远不会被执行。
});
test('skip() method', (t) => {
// 如果测试包含额外的逻辑,则务必返回这里。
t.skip();
});
test('skip() method with message', (t) => {
// 如果测试包含额外的逻辑,则务必返回这里。
t.skip('this is skipped');
});
describe/it 语法#
运行测试也可以使用 describe
来声明套件和 it
来声明测试。
套件用于将相关测试组织和分组在一起。
it
是 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
模块导入的
import { describe, it } from 'node:test';
const { describe, it } = require('node:test');
only
测试#
如果 Node.js 使用 --test-only
命令行选项启动,则可以通过将 only
选项传给应该运行的测试来跳过除选定子集之外的所有顶层测试。
当运行带有 only
选项集的测试时,所有子测试也会运行。
测试上下文的 runOnly()
方法可用于在子测试级别实现相同的行为。
// 假设 Node.js 使用 --test-only 命令行选项运行。
// 设置了 'only' 选项,因此运行此测试。
test('this test is run', { only: true }, async (t) => {
// 在此测试中,默认运行所有子测试。
await t.test('running subtest');
// 可以使用 'only' 选项更新测试上下文以运行子测试。
t.runOnly(true);
await t.test('this subtest is now skipped');
await t.test('this subtest is run', { only: true });
// 切换上下文以执行所有测试。
t.runOnly(false);
await t.test('this subtest is now run');
// 显式地不要运行这些测试。
await t.test('skipped subtest 3', { only: false });
await t.test('skipped subtest 4', { skip: true });
});
// 未设置 'only' 选项,因此跳过此测试。
test('this test is not run', () => {
// 此代码未运行。
throw new Error('fail');
});
无关的异步活动#
一旦测试函数完成执行,则 TAP 结果会尽快输出,同时保持测试的顺序。 但是,测试函数可能会生成比测试本身寿命更长的异步活动。 测试运行器处理此类活动,但不会延迟报告测试结果以适应它。
在下面的示例中,测试完成时仍然有两个 setImmediate()
操作未完成。
第一个 setImmediate()
尝试创建新的子测试。
因为父测试已经完成并输出结果,新的子测试立即被标记为失败,并在文件的 TAP 输出的顶层报告。
第二个 setImmediate()
创建了 uncaughtException
事件。
源自已完成测试的 uncaughtException
和 unhandledRejection
事件由 test
模块处理,并在文件的 TAP 输出的顶层报告为诊断警告。
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');
});
// 此行之后测试结束。
});
从命令行运行测试#
可以通过传入 --test
标志从命令行调用 Node.js 测试运行程序:
node --test
默认情况下,Node.js 将递归搜索当前目录以查找匹配特定命名约定的 JavaScript 源文件。 匹配文件作为测试文件执行。 有关预期测试文件命名约定和行为的更多信息可以在测试运行器执行模型章节中找到。
或者,可以提供一个或多个路径作为 Node.js 命令的最终参数,如下所示。
node --test test1.js test2.mjs custom_test_dir/
在本例中,测试运行程序将执行文件 test1.js
和 test2.mjs
。
测试运行器还将递归搜索 custom_test_dir/
目录以查找要执行的测试文件。
测试运行器执行模型#
当搜索要执行的测试文件时,测试运行器的行为如下:
- 执行用户显式提供的任何文件。
- 如果用户没有显式地指定任何路径,则递归搜索当前工作目录中指定的文件,如以下步骤所示。
- 除非用户显式地提供,否则跳过
node_modules
目录。 - 如果遇到名为
test
的目录,则测试运行程序将递归搜索所有.js
、.cjs
和.mjs
文件。 所有这些文件都被视为测试文件,不需要匹配下面详述的特定命名约定。 这是为了适应将所有测试放在单个test
目录中的项目。 - 在所有其他目录中,匹配以下模式的
.js
、.cjs
和.mjs
文件被视为测试文件:^test$
- 基本名称为字符串'test'
的文件。 示例:test.js
、test.cjs
、test.mjs
。^test-.+
- 基本名称以字符串'test-'
开头,后跟一个或多个字符的文件。 示例:test-example.js
、test-another-example.mjs
。.+[\.\-\_]test$
- 基本名称以.test
、-test
或_test
结尾的文件,前面有一个或多个字符。 示例:example.test.js
、example-test.cjs
、example_test.mjs
。- Node.js 理解的其他文件类型,例如
.node
和.json
,不会由测试运行程序自动执行,但如果在命令行上显式地提供,则支持。
每个匹配的测试文件都在单独的子进程中执行。
如果子进程以退出代码 0 结束,则认为测试通过。
否则,认为测试失败。
测试文件必须是 Node.js 可执行文件,但不需要在内部使用 node:test
模块。
test([name][, options][, fn])
#
name
<string> 测试的名称,报告测试结果时显示。 默认值: Thename
fn
的属性,如果fn
没有名称,则为'<anonymous>'
。options
<Object> 测试的配置选项。 支持以下属性:concurrency
<number> 可同时运行的测试数。 如果未指定,则子测试从其父测试继承此值。 默认值:1
。only
<boolean> 如果为真,并且测试上下文配置为运行only
测试,则将运行此测试。 否则跳过测试。 默认值:false
。skip
<boolean> | <string> 如果为真,则跳过测试。 如果提供了字符串,则该字符串将作为跳过测试的原因显示在测试结果中。 默认值:false
。todo
<boolean> | <string> 如果为真,则测试标记为TODO
。 如果提供了字符串,则该字符串会显示在测试结果中作为测试为TODO
的原因。 默认值:false
。
fn
<Function> | <AsyncFunction> 被测试的函数。 此函数的第一个参数是TestContext
对象。 如果测试使用回调,则回调函数作为第二个参数传入。 默认值: 无操作的函数。- 返回: <Promise> 测试完成后使用
undefined
解决。
test()
函数是从 test
模块导入的值。
每次调用此函数都会在 TAP 输出中创建一个测试点。
传给 fn
参数的 TestContext
对象可用于执行与当前测试相关的操作。
示例包括跳过测试、添加额外的 TAP 诊断信息、或创建子测试。
test()
返回 Promise
,一旦测试完成就解决。
返回值通常可以被顶层测试丢弃。
但是,应该使用子测试的返回值来防止父测试先完成并取消子测试,如下例所示。
test('top level test', async (t) => {
// 如果在下一行删除了 'await',
// 则以下子测试中的 setTimeout() 将导致它的父测试寿命超过其父测试。
// 一旦父测试完成,则它将取消所有未完成的子测试。
await t.test('longer running subtest', async (t) => {
return new Promise((resolve, reject) => {
setTimeout(resolve, 1000);
});
});
});
describe([name][, options][, fn])
#
name
<string> 套件名称,报告测试结果时显示。 默认值: Thename
fn
的属性,如果fn
没有名称,则为'<anonymous>'
。options
<Object> 套件的配置选项。 支持与test([name][, options][, fn])
相同的选项fn
<Function> 套件下的函数。 声明所有子测试和子套件的同步函数。 默认值: 无操作的函数。- 返回:
undefined
。
从 node:test
模块导入的 describe()
函数。
每次调用此函数都会在 TAP 输出中创建一个子测试和一个测试点。
调用顶层 describe
函数之后,所有顶层测试和套件都将执行
describe.skip([name][, options][, fn])
#
跳过套件的简写,与 describe([name], { skip: true }[, fn])
相同。
describe.todo([name][, options][, fn])
#
将套件标记为 TODO
的简写,与 describe([name], { todo: true }[, fn])
相同。
it([name][, options][, fn])
#
name
<string> 测试的名称,报告测试结果时显示。 默认值: Thename
fn
的属性,如果fn
没有名称,则为'<anonymous>'
。options
<Object> 套件的配置选项。 支持与test([name][, options][, fn])
相同的选项。fn
<Function> | <AsyncFunction> 被测试的函数。 如果测试使用回调,则回调函数作为参数传入。 默认值: 无操作的函数。- 返回:
undefined
。
it()
函数是从 node:test
模块导入的值。
每次调用此函数都会在 TAP 输出中创建一个测试点。
it.skip([name][, options][, fn])
#
跳过测试的简写,与 it([name], { skip: true }[, fn])
相同。
it.todo([name][, options][, fn])
#
将测试标记为 TODO
的简写,与 it([name], { todo: true }[, fn])
相同。
TestContext
类#
TestContext
的实例被传给每个测试函数,以便与测试运行器交互。
但是,TestContext
构造函数没有作为 API 的一部分公开。
context.diagnostic(message)
#
message
<string> 要显示为 TAP 诊断的消息。
此函数用于将 TAP 诊断写入输出。 任何诊断信息都包含在测试结果的末尾。 此函数不返回值。
test('top level test', (t) => {
t.diagnostic('A diagnostic message');
});
context.runOnly(shouldRunOnlyTests)
#
shouldRunOnlyTests
<boolean> 是否运行only
测试。
如果 shouldRunOnlyTests
为真,则测试上下文将只运行设置了 only
选项的测试。
否则,将运行所有测试。
如果 Node.js 不是使用 --test-only
命令行选项启动的,则此函数是无操作的。
test('top level test', (t) => {
// 可以将测试上下文设置为使用 'only' 选项运行子测试。
t.runOnly(true);
return Promise.all([
t.test('this subtest is now skipped'),
t.test('this subtest is run', { only: true }),
]);
});
context.skip([message])
#
message
<string> 要在 TAP 输出中显示的可选跳过消息。
此函数使测试的输出指示测试已跳过。
如果提供了 message
,则它将包含在 TAP 输出中。
调用 skip()
不会终止测试函数的执行。
此函数不返回值。
test('top level test', (t) => {
// 如果测试包含额外的逻辑,则务必返回这里。
t.skip('this is skipped');
});
context.todo([message])
#
message
<string> 要在 TAP 输出中显示的可选TODO
消息。
此函数将 TODO
指令添加到测试的输出中。
如果提供了 message
,则它将包含在 TAP 输出中。
调用 todo()
不会终止测试函数的执行。
此函数不返回值。
test('top level test', (t) => {
// 此测试标记为 `TODO`
t.todo('this is a todo');
});
context.test([name][, options][, fn])
#
name
<string> 子测试的名称,在报告测试结果时显示。 默认值: Thename
fn
的属性,如果fn
没有名称,则为'<anonymous>'
。options
<Object> 子测试的配置选项。 支持以下属性:concurrency
<number> 可同时运行的测试数。 如果未指定,则子测试从其父测试继承此值。 默认值:1
。only
<boolean> 如果为真,并且测试上下文配置为运行only
测试,则将运行此测试。 否则跳过测试。 默认值:false
。skip
<boolean> | <string> 如果为真,则跳过测试。 如果提供了字符串,则该字符串将作为跳过测试的原因显示在测试结果中。 默认值:false
。todo
<boolean> | <string> 如果为真,则测试标记为TODO
。 如果提供了字符串,则该字符串会显示在测试结果中作为测试为TODO
的原因。 默认值:false
。
fn
<Function> | <AsyncFunction> 被测试的函数。 此函数的第一个参数是TestContext
对象。 如果测试使用回调,则回调函数作为第二个参数传入。 默认值: 无操作的函数。- 返回: <Promise> 测试完成后使用
undefined
解决。
此函数用于在当前测试下创建子测试。
此函数的行为方式与顶层的 test()
函数相同。
test('top level test', async (t) => {
await t.test(
'This is a subtest',
{ only: false, skip: false, concurrency: 1, todo: false },
(t) => {
assert.ok('some relevant assertion here');
}
);
});