菜单

内部测试系统

相关源文件

本文档介绍了 Node.js 项目用于自我测试的内部测试系统。它涵盖了测试组织、执行模式、测试类别以及特定于平台的配置。有关 Node.js 应用程序开发者可用的 Node.js 测试运行器 API 的信息,请参阅测试运行器

概述

Node.js 内部测试系统旨在确保跨多个平台、体系结构和配置的可靠性。它根据执行模式和资源需求将测试组织成不同的类别,并提供处理特定于平台测试行为的机制。

来源

测试类别

Node.js 测试被组织成几个不同的类别,每个类别都有不同的执行模式和资源需求。

类别描述执行模式资源使用
并行可以并发运行的小型单元测试并发
顺序必须按顺序运行的测试串口中等
Pummel对系统施加重负荷的压力测试串口
Async-hooksasync_hooks API 的测试混合可变
Node-APINode-API (N-API) 的测试混合可变
Report诊断报告功能的测试混合可变
Abort中止行为和信号处理的测试混合可变

每个测试类别在 test/ 文件夹中都有自己的目录,并且可能包含一个 .status 文件,该文件指定了特定于平台的行为。

来源

测试执行架构

下图说明了 Node.js 测试系统的整体架构。

来源

状态文件和特定于平台的测试行为

状态文件是测试系统的关键组成部分,允许测试在不同的平台和配置下表现出不同的行为。每个测试类别都可以有一个 .status 文件,该文件定义了特定于条件的行为。

状态文件格式

状态文件遵循一致的格式。

prefix <category>

# Comment lines start with #
[<condition>] # This section applies when condition is true
test-name: PASS,FLAKY
another-test: SKIP

条件可以包括:

  • true - 适用于所有平台
  • $system==win32 - 仅限 Windows
  • $system==linux - 仅限 Linux
  • $system==macos - 仅限 macOS
  • $arch==arm || $arch==arm64 - ARM 架构
  • $system==solaris - Solaris/SmartOS
  • $system==freebsd - FreeBSD
  • $system==aix - AIX
  • $system==ibmi - IBM i
  • $asan==on - 已启用 AddressSanitizer

测试行为可以指定为:

  • PASS - 测试应通过
  • SKIP - 测试应被跳过
  • FLAKY - 测试有时可能会失败(通常与 PASS 配对)

来源

特定于平台的挑战与解决方案

Node.js 的测试系统处理各种特定于平台的挑战。

平台常见问题解决方案
Windows文件系统,路径分隔符特定于平台的测试标志
Linux性能变化宽松的时间断言
macOS网络超时将测试标记为 flaky
ARM/ARM64性能、加密差异跳过加密测试,放宽时间限制
Solaris/SmartOS域和错误处理将域测试标记为 flaky
IBM i网络和套接字相关跳过受影响的测试

来源

测试结构和常见测试模式

Node.js 测试通常遵循此结构:

  1. 导入所需模块

  2. 使用 common 模块进行测试工具

    • 特定于平台的超时
    • 测试断言和期望
    • 在特定平台上跳过测试
  3. 使用 Node.js 内置的 assert 模块编写断言

  4. 对于较新的测试,请使用 Node.js 测试运行器 API。

来源

测试复杂功能

对于性能钩子、工作线程或文件系统操作等复杂功能,测试通常使用:

  1. 倒计时:用于确保异步操作完成。
  2. 计时器:用于测试延迟和超时。
  3. Mock 函数:测试回调函数是否按预期调用。
  4. 特定于平台的调整:为不同体系结构调整测试。

来源

测试运行器实现

Node.js 测试运行器通过以下步骤执行测试:

  1. 发现:在适当的目录中查找测试文件。
  2. 状态文件处理:应用特定于平台的行为。
  3. 执行:根据其类别运行测试。
    • 并行:在单独的进程中并发运行。
    • 顺序:一个接一个地运行。
    • Pummel:按顺序运行,使用更多资源。
  4. 报告:收集和汇总测试结果。

对于特殊测试类型(如 Node-API 或 C++ 测试),在执行测试之前可能需要额外的构建步骤。

来源

常见测试失败及处理

测试系统对常见类型的测试失败有特殊处理。

  1. Flaky 测试:有时失败的测试会标记为 PASS,FLAKY
  2. 特定于平台的失败:使用状态文件在有问题的平台上跳过。
  3. 对时间敏感的测试:通常标记为 flaky 或给予特定于平台的超时。
  4. 资源密集型测试:放在 pummel 类别中。

通常需要特殊处理的问题示例:

  • 具有竞争条件的测试
  • 对系统负载敏感的测试
  • 依赖于特定网络行为的测试
  • 在不同体系结构上使用加密操作的测试

来源

与 CI/CD 集成

测试系统与 GitHub Actions 集成,以在多个平台、Node.js 版本和配置上运行测试。CI 系统运行:

  1. 在主要平台上的所有测试类别
  2. 在不太常见的平台上的测试子集
  3. 特殊配置(带 ASan、覆盖率等)

当对 Node.js 提出更改建议时,CI 系统会自动运行测试套件,以验证兼容性并防止回归。

常用的测试模块

Node.js 测试中常用几个模块:

模块目的
common共享的测试工具和助手。
assert标准断言。
tmpdir临时目录管理。
countdown跟踪多个异步操作的完成情况。
node:test测试运行器 API(较新的测试)。

来源

编写有效的测试

为 Node.js 内部编写测试时,请遵循以下最佳实践:

  1. 将测试放在适当的类别中。
  2. 使用 common 模块以获得跨平台一致性。
  3. 处理特定于平台的行为。
  4. 确保测试完成后进行清理。
  5. 在状态文件中标记预期的 flaky 行为。
  6. 使用清晰的断言和描述性消息。
  7. 测试成功和失败路径。

结论

Node.js 内部测试系统为跨不同平台、配置和环境的测试提供了一个强大的框架。其按不同测试类别组织的结构,结合特定于平台的.status 文件,可以精确控制测试执行。