Skip to content

测试基础设施 ​

INFO

本文旨在邀请大家分享改进我们测试基础设施的想法, 请随时在 Discord 上联系我们。

在 Oxc 中,正确性和可靠性受到极度重视。

我们花费大量时间加强测试基础设施,以防止问题传播到下游工具。

解析器 ​

一致性 ​

来自 Test262、Babel 和 TypeScript 的解析器测试用于测试 JavaScript、TypeScript 和 JSX 语法。

共享的 tasks/coverage 测试工具会在解析器、语义分析、代码生成、转换、压缩和 ESTree 测试中复用这些测试夹具集合。

对于 Test262,会包含所有 stage 4 和正则表达式测试。

所有一致性结果都存储在快照文件中,以便跟踪变化:

所有语法错误都写入这些快照文件以便对比变化。

模糊测试 ​

为了确保解析器在遇到随机数据时不会 panic,使用了三个模糊测试工具:

  1. cargo-fuzz 用于向解析器发送随机数据。
  2. shift-fuzzer-js 由 bakkot 开发,用于生成随机但有效的 AST。
  3. Automated-Fuzzer 由 qarmin 开发,会主动报告崩溃。

内存安全 ​

Oxc 使用 arena 分配器作为 AST 和其他数据的内存分配器。 任何 AST 节点类型都没有 Drop 实现。 这由 Oxc 分配器在编译时强制执行:如果代码尝试在 arena 中分配实现了 Drop 的类型,就会产生编译错误。这样可以在静态层面确保拥有堆分配数据的类型不会存储在 arena 中,避免内存泄漏。

不安全代码 ​

Oxc 使用 unsafe 代码进行性能优化。我们的目标是将 unsafe 限制在对外提供安全 API 的自包含数据结构中。Miri 会在包含这些结构的 crate 发生相关变更时运行。

检查器 ​

快照诊断 ​

所有检查器诊断信息都会写入快照文件,用于回归测试。

例如:

javascript
 ⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
  ╭─[adjacent_overload_signatures.tsx:3:18]
2 │         function foo(s: string);
3 │         function foo(n: number);
  ·                  ───
4 │         type bar = number;
5 │         function foo(sn: string | number) {}
  ·                  ───
6 │       }
  ╰────

生态系统 CI ​

oxc-ecosystem-ci 针对大型仓库运行 Oxlint 和 Oxfmt。Oxlint 检查误报、回归和 panic;Oxfmt 检查格式差异、代码丢失、错误和 panic。测试的仓库包括:

幂等性 ​

幂等性测试用于所有工具的集成测试和端到端测试。

幂等性测试遵循以下过程:

javascript
let sourceText = "foo";
let printed = tool(sourceText);
let printed2 = tool(printed);
assert(printed == printed2);

例如,幂等地最小化一段代码应该产生相同的结果。

代码生成器、转换器、压缩器和格式化器都会在 Test262、Babel 和 TypeScript 测试文件上进行幂等测试。

集成测试 ​

集成测试优于单元测试。

codecov 目前报告 代码覆盖率 行覆盖率。

端到端 ​

仓库 monitor-oxc 针对 npm-high-impact 中前 3000 个 npm 包执行端到端测试。

它会对这些软件包的文件运行代码生成、转换、压缩、名称混淆、空白移除和格式化。

其 package.json 将这些软件包列为依赖项:

json
"devDependencies": {
  "@aashutoshrathi/word-wrap": "latest",
  "@actions/http-client": "latest",
  "@adobe/css-tools": "latest",
  "@alloc/quick-lru": "latest",
 ...
  "zip-stream": "latest",
  "zod": "latest",
  "zone.js": "latest",
  "zustand": "latest"
}

以及一个导入这些包并断言导入的测试文件:

src/dynamic.test.mjs

javascript
import test from "node:test";
import assert from "node:assert";
test("@aashutoshrathi/word-wrap", () => import("@aashutoshrathi/word-wrap").then(assert.ok));
test("@actions/http-client", () => import("@actions/http-client").then(assert.ok));
test("@adobe/css-tools", () => import("@adobe/css-tools").then(assert.ok));
test("@alloc/quick-lru", () => import("@alloc/quick-lru").then(assert.ok));
...
test("zod", () => import("zod").then(assert.ok));
test("zone.js", () => import("zone.js").then(assert.ok));
test("zustand", () => import("zustand").then(assert.ok));
test("zwitch", () => import("zwitch").then(assert.ok));

此测试文件在每个工具(代码生成器、转换器、最小化器等)重写 node_modules 中的所有文件后运行。

该工作流每三小时运行一次。

还会针对 Vue 测试隔离声明。


如果你对如何改进我们的测试基础设施有任何想法, 欢迎在 Discord 上联系我们。