测试框架提供了 Deno 内置的测试运行器功能,包括测试发现、执行、过滤和报告。该系统使开发者能够使用 Deno.test() API 调用编写和运行测试,并通过 deno test 命令或 IDE 集成执行它们。
有关基准测试的信息,请参阅 基准测试。有关 CLI 命令处理的信息,请参阅 命令处理。
测试框架由几个相互连接的组件组成,它们在 CLI 和语言服务器协议 (LSP) 环境中处理测试发现、执行和报告。
测试框架核心架构
来源:cli/tools/test/mod.rs1-100 cli/ops/testing.rs24-43 cli/lsp/testing/server.rs47-61
测试发现通过两种主要机制进行:用于 LSP 集成的静态 AST 分析和 JavaScript 执行期间的动态注册。
LSP 系统使用 AST 解析来发现测试而无需执行代码,从而实现 IDE 功能,如测试探索和调试。
静态测试发现流程
TestCollector 实现 Visit trait 以遍历 AST 节点并识别测试模式
Deno.test("name", fn)Deno.test({ name: "test", fn: () => {} })const { test } = Deno; test("name", fn)t.step("step name", fn)来源:cli/lsp/testing/collectors.rs445-467 cli/lsp/testing/collectors.rs470-553
在测试执行期间,JavaScript Deno.test() 调用通过 Rust ops 进行注册,创建包含测试元数据的 TestDescription 对象。
动态测试注册
来源:cli/ops/testing.rs92-131 cli/tools/test/mod.rs280-291
测试执行遵循多阶段管道,处理测试发现、过滤、工作区创建和结果收集。
测试执行管道
来源:cli/tools/test/mod.rs855-880 cli/tools/test/mod.rs650-701
该框架使用事件驱动的架构来在工作区和主线程之间通信测试进度和结果。
| 事件类型 | 目的 | 数据 |
|---|---|---|
TestEvent::Register | 测试发现 | TestDescriptions |
TestEvent::Plan | 执行计划 | 带有总数的 TestPlan |
TestEvent::Wait | 测试开始 | test_id |
TestEvent::Result | 测试完成 | 带有时间的 TestResult |
TestEvent::StepRegister | 测试步骤发现 | TestStepDescription |
TestEvent::StepResult | 步骤完成 | TestStepResult |
TestEvent::UncaughtError | 运行时错误 | JsError 详情 |
来源:cli/tools/test/mod.rs510-530 cli/tools/test/channel.rs1-50
测试框架实现了复杂的权限管理,允许测试在保持安全隔离的同时以提升或受限的权限运行。
权限声明/恢复周期
权限系统使用基于令牌的方法,其中 op_pledge_test_permissions 返回一个 UUID 令牌,该令牌必须提供给 op_restore_test_permissions 以防止权限升级攻击。
来源:cli/ops/testing.rs48-86 deno_runtime/permissions.rs
Deno 的测试框架包含内置的清理程序,可检测资源泄漏和挂起的异步操作,以确保测试隔离并防止测试不稳定。
清理程序检测流程
清理程序通过以下方式工作:
MAX_SANITIZER_LOOP_SPINS)来源:cli/tools/test/mod.rs1176-1233 cli/tools/test/mod.rs118-173
该框架提供多种过滤运行哪些测试的机制,支持 CLI 参数和编程选择。
测试过滤机制
TestFilter::includes() 方法按顺序应用过滤器
来源:cli/tools/test/mod.rs176-225 cli/lsp/testing/execution.rs134-157
语言服务器协议集成使得 IDE 可以进行测试发现、执行和调试,而无需完全调用 CLI。
LSP 测试集成架构
TestServer 维护两个后台线程:
来源:cli/lsp/testing/server.rs62-208 cli/lsp/testing/execution.rs159-190
测试步骤提供分层测试组织,允许测试包含具有独立通过/失败状态和计时信息的子测试。
测试步骤层级
测试步骤维护与其父测试和根测试的引用,从而实现正确的嵌套和结果聚合。失败的步骤会导致其父测试失败,但步骤失败与测试失败是分开报告的。
来源:cli/ops/testing.rs142-172 cli/tools/test/mod.rs475-493
测试框架支持多种输出格式和报告机制,以满足不同的用例。
| 报告器 | 目的 | 输出格式 |
|---|---|---|
PrettyTestReporter | 人类可读的 CLI 输出 | 彩色终端文本 |
DotTestReporter | 最小化的进度指示 | 每个测试一个字符 |
JunitTestReporter | CI/CD 集成 | JUnit XML 格式 |
TapTestReporter | TAP 协议兼容 | TAP 格式输出 |
CompoundTestReporter | 多输出 | 组合多个报告器 |
报告器系统使用 TestReporter trait 来标准化不同输出类型的格式。报告器接收 TestEvent 消息,并根据其特定要求进行格式化。
来源:cli/tools/test/reporters/mod.rs1-50 cli/tools/test/mod.rs606-648