import Test from "/snippets/cli/test.mdx";
Bun 附带一个快速、内置、与 Jest 兼容的测试运行器。测试使用 Bun 运行时执行,并支持以下功能。
- TypeScript 和 JSX
- 生命周期钩子
- 快照测试
- UI 和 DOM 测试
- 使用
--watch的监视模式 - 使用
--preload的脚本预加载
NOTE
Bun 致力于与 Jest 兼容,但并非所有功能都已实现。要跟踪兼容性,请参阅 [此跟踪问题](https://github.com/oven-sh/bun/issues/1825)。运行测试
bun test测试使用 JavaScript 或 TypeScript 编写,采用类似 Jest 的 API。有关完整文档,请参阅 编写测试。
import { expect, test } from "bun:test";
test("2 + 2", () => {
expect(2 + 2).toBe(4);
});测试运行器会递归搜索工作目录中符合以下模式的文件:
*.test.{js|jsx|ts|tsx}*_test.{js|jsx|ts|tsx}*.spec.{js|jsx|ts|tsx}*_spec.{js|jsx|ts|tsx}
你可以通过向 bun test 传递额外的位置参数来过滤要运行的 测试文件。任何路径与过滤器之一匹配的测试文件都将运行。通常,这些过滤器将是文件或目录名称;目前不支持 glob 模式。
bun test <filter> <filter> ...要按 测试名称 过滤,请使用 -t/--test-name-pattern 标志。
# 运行名称中包含 "addition" 的所有测试或测试套件
bun test --test-name-pattern addition要在测试运行器中运行特定文件,请确保路径以 ./ 或 / 开头,以区别于过滤器名称。
bun test ./test/specific-file.test.ts测试运行器在单个进程中运行所有测试。它加载所有 --preload 脚本(有关详细信息,请参阅 生命周期),然后运行所有测试。如果测试失败,测试运行器将以非零退出码退出。
CI/CD 集成
bun test 支持各种 CI/CD 集成。
GitHub Actions
bun test 自动检测是否在 GitHub Actions 内运行,并将 GitHub Actions 注解直接输出到控制台。
除了在工作流中安装 bun 并运行 bun test 外,不需要其他配置。
如何在 GitHub Actions 工作流中安装 bun
要在 GitHub Actions 工作流中使用 bun test,请添加以下步骤:
jobs:
build:
name: build-app
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install bun
uses: oven-sh/setup-bun@v2
- name: Install dependencies # 假设你的项目有依赖
run: bun install # 如果你更喜欢,可以使用 npm/yarn/pnpm 代替
- name: Run tests
run: bun test从这里开始,你将获得 GitHub Actions 注解。
JUnit XML 报告(GitLab 等)
要将 bun test 与 JUnit XML 报告器一起使用,可以将 --reporter=junit 与 --reporter-outfile 结合使用。
bun test --reporter=junit --reporter-outfile=./bun.xml这将像往常一样继续输出到 stdout/stderr,并在测试运行结束时将 JUnit XML 报告写入给定路径。
JUnit XML 是在 CI/CD 管道中报告测试结果的一种流行格式。
超时
使用 --timeout 标志指定 每个测试 的超时时间(以毫秒为单位)。如果测试超时,它将被标记为失败。默认值为 5000。
# 默认值为 5000
bun test --timeout 20并发测试执行
默认情况下,Bun 在每个测试文件中按顺序运行所有测试。你可以启用并发执行以并行运行异步测试,显著加快具有独立测试的测试套件。
--concurrent 标志
使用 --concurrent 标志在各自的文件内并发运行所有测试:
bun test --concurrent启用此标志后,所有测试将并行运行,除非明确标记为 test.serial。
--max-concurrency 标志
使用 --max-concurrency 标志控制同时运行的最大测试数:
# 限制为 4 个并发测试
bun test --concurrent --max-concurrency 4
# 默认值:20
bun test --concurrent这有助于在运行许多并发测试时防止资源耗尽。默认值为 20。
test.concurrent
标记单个测试以并发运行,即使未使用 --concurrent 标志:
import { test, expect } from "bun:test";
// 这些测试彼此并行运行
test.concurrent("concurrent test 1", async () => {
await fetch("/api/endpoint1");
expect(true).toBe(true);
});
test.concurrent("concurrent test 2", async () => {
await fetch("/api/endpoint2");
expect(true).toBe(true);
});
// 此测试按顺序运行
test("sequential test", () => {
expect(1 + 1).toBe(2);
});test.serial
强制测试按顺序运行,即使启用了 --concurrent 标志:
import { test, expect } from "bun:test";
let sharedState = 0;
// 这些测试必须按顺序运行
test.serial("first serial test", () => {
sharedState = 1;
expect(sharedState).toBe(1);
});
test.serial("second serial test", () => {
// 依赖于上一个测试
expect(sharedState).toBe(1);
sharedState = 2;
});
# 如果启用了 --concurrent,此测试可以并发运行
test("independent test", () => {
expect(true).toBe(true);
});
// 链接测试限定符
test.failing.each([1, 2, 3])("chained qualifiers %d", input => {
expect(input).toBe(0); // 此测试预计对每个输入都失败
});重新运行测试
使用 --rerun-each 标志将每个测试运行多次。这对于检测不稳定或非确定性测试失败很有用。
bun test --rerun-each 100随机化测试执行顺序
使用 --randomize 标志以随机顺序运行测试。这有助于检测依赖于共享状态或执行顺序的测试。
bun test --randomize使用 --randomize 时,随机化使用的种子将显示在测试摘要中:
bun test --randomize# ... 测试输出 ...
--seed=12345
2 pass
8 fail
Ran 10 tests across 2 files. [50.00ms]使用 --seed 的可重现随机顺序
使用 --seed 标志指定随机化的种子。这允许你在调试依赖于顺序的失败时重现相同的测试顺序。
# 重现以前的随机化运行
bun test --seed 123456--seed 标志隐含 --randomize,因此你不需要同时指定两者。使用相同的种子值将始终产生相同的测试执行顺序,使调试由测试间依赖关系引起的间歇性失败变得更加容易。
使用 --bail 退出
使用 --bail 标志在预定数量的测试失败后提前中止测试运行。默认情况下,Bun 将运行所有测试并报告所有失败,但有时在 CI 环境中,最好提前终止以减少 CPU 使用率。
# 失败 1 次后退出
bun test --bail
# 失败 10 次后退出
bun test --bail=10监视模式
与 bun run 类似,你可以将 --watch 标志传递给 bun test 以监视更改并重新运行测试。
bun test --watch生命周期钩子
Bun 支持以下生命周期钩子:
| 钩子 | 描述 |
|---|---|
beforeAll | 在所有测试之前运行一次。 |
beforeEach | 在每个测试之前运行。 |
afterEach | 在每个测试之后运行。 |
afterAll | 在所有测试之后运行一次。 |
这些钩子可以在测试文件内定义,也可以在使用 --preload 标志预加载的单独文件中定义。
bun test --preload ./setup.ts有关完整文档,请参阅 测试 > 生命周期。
模拟
使用 mock 函数创建模拟函数。
import { test, expect, mock } from "bun:test";
const random = mock(() => Math.random());
test("random", () => {
const val = random();
expect(val).toBeGreaterThan(0);
expect(random).toHaveBeenCalled();
expect(random).toHaveBeenCalledTimes(1);
});或者,你可以使用 jest.fn(),它的行为完全相同。
import { test, expect, mock } from "bun:test";
import { test, expect, jest } from "bun:test";
const random = mock(() => Math.random());
const random = jest.fn(() => Math.random()); 有关完整文档,请参阅 测试 > 模拟。
快照测试
bun test 支持快照。
// toMatchSnapshot 的示例用法
import { test, expect } from "bun:test";
test("snapshot", () => {
expect({ a: 1 }).toMatchSnapshot();
});要更新快照,请使用 --update-snapshots 标志。
bun test --update-snapshots有关完整文档,请参阅 测试 > 快照。
UI 和 DOM 测试
Bun 与流行的 UI 测试库兼容:
有关完整文档,请参阅 测试 > DOM 测试。
性能
Bun 的测试运行器速度很快。
AI 代理集成
在使用 AI 编码助手使用 Bun 的测试运行器时,你可以启用更安静的输出以提高可读性并减少上下文噪音。此功能最大限度地减少测试输出的冗长,同时保留必要的失败信息。
环境变量
设置以下任何环境变量以启用 AI 友好的输出:
CLAUDECODE=1- 用于 Claude CodeREPL_ID=1- 用于 ReplitAGENT=1- 通用 AI 代理标志
行为
当检测到 AI 代理环境时:
- 仅详细显示测试失败
- 隐藏通过、跳过和待办测试指示器
- 汇总统计信息保持不变
# 示例:为 Claude Code 启用安静输出
CLAUDECODE=1 bun test
# 仍然显示失败和摘要,但隐藏冗长的通过测试输出此功能在 AI 辅助开发工作流中特别有用,减少的输出冗长提高了上下文效率,同时保持了对测试失败的可见性。