Skip to main content
Bun 搭载了一个快速的内置 Jest 兼容测试运行器。测试在 Bun 运行时执行,并支持以下功能。
  • TypeScript 和 JSX
  • 生命周期钩子
  • 快照测试
  • UI 与 DOM 测试
  • 使用 --watch 的监视模式
  • 使用 --preload 的脚本预加载
Bun 旨在兼容 Jest,但并非所有功能均已实现。要跟踪兼容性,请查看此跟踪问题

运行测试

terminal
bun test
测试使用 JavaScript 或 TypeScript 编写,采用类似 Jest 的 API。完整文档请参阅编写测试
https://mintcdn.com/ikxin/RzFFGbzo0-4huILA/icons/typescript.svg?fit=max&auto=format&n=RzFFGbzo0-4huILA&q=85&s=a3dffd2241f05776d3bd25171d0c5a79math.test.ts
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 模式。
terminal
bun test <filter> <filter> ...
如果要根据 测试名称 过滤,使用 -t/--test-name-pattern 标志。
terminal
# 运行名称中含 "addition" 的所有测试或测试套件
bun test --test-name-pattern addition
若要运行特定文件,确保路径以 .// 开头,以区别于筛选名。
terminal
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,添加如下步骤:
.github/workflows/test.yml
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 等)

要结合 JUnit XML 报告器使用 bun test,可以搭配 --reporter=junit--reporter-outfile
terminal
bun test --reporter=junit --reporter-outfile=./bun.xml
这会继续像往常一样输出到 stdout/stderr,且在测试运行结束时写入指定路径的 JUnit XML 报告。 JUnit XML 是 CI/CD 管道中报告测试结果的流行格式。

超时设置

使用 --timeout 标志指定每个测试的超时时间(毫秒)。若测试超时,则判为失败。默认值为 5000
terminal
# 默认值是 5000
bun test --timeout 20

并发测试执行

默认情况下,Bun 在每个测试文件内顺序执行所有测试。你可以启用并发执行,让异步测试并行运行,这能显著加速测试套件中的独立测试。

--concurrent 标志

使用 --concurrent 标志,实现各测试文件内部的所有测试并发执行:
terminal
bun test --concurrent
启用该标志时,所有测试将并行运行,除非显式加上 test.serial 标记。

--max-concurrency 标志

--max-concurrency 标志控制最大并发测试数量:
terminal
# 限制最大并发测试为 4 个
bun test --concurrent --max-concurrency 4

# 默认值是 20
bun test --concurrent
这有助于防止资源耗尽。默认限制为 20。

test.concurrent

单独标记测试为并发执行,即使未使用 --concurrent 也能并行运行:
https://mintcdn.com/ikxin/RzFFGbzo0-4huILA/icons/typescript.svg?fit=max&auto=format&n=RzFFGbzo0-4huILA&q=85&s=a3dffd2241f05776d3bd25171d0c5a79math.test.ts
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 标志,也强制测试顺序执行:
https://mintcdn.com/ikxin/RzFFGbzo0-4huILA/icons/typescript.svg?fit=max&auto=format&n=RzFFGbzo0-4huILA&q=85&s=a3dffd2241f05776d3bd25171d0c5a79math.test.ts
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 标志使每个测试运行多次,有助于检测不稳定或非确定性的测试失败。
terminal
bun test --rerun-each 100

随机化测试执行顺序

使用 --randomize 标志以随机顺序运行测试,有助于发现依赖共享状态或执行顺序的测试。
terminal
bun test --randomize
启用 --randomize 时,随机种子会显示在测试摘要中:
terminal
bun test --randomize
# ... 测试输出 ...
 --seed=12345
 2 pass
 8 fail
Ran 10 tests across 2 files. [50.00ms]

使用 --seed 实现可复现的随机顺序

--seed 标志指定随机种子,以便调试顺序依赖失败时复现相同测试顺序。
terminal
# 复现之前的随机运行顺序
bun test --seed 123456
--seed 标志隐含启用 --randomize,因此无需同时指定两者。使用相同种子值总是产生相同的测试执行顺序,使调试间歇性失败更为简单。

失败即停止 --bail

使用 --bail 标志,在达到指定失败次数后提前中止测试运行。默认情况下,Bun 会执行全部测试并报告所有失败,但在 CI 环境中,提前终止可减少 CPU 资源占用。
terminal
# 发生 1 次失败即停止
bun test --bail

# 发生 10 次失败即停止
bun test --bail=10

监视模式

类似于 bun run,你可以传入 --watch 标志,让 bun test 监控文件变化并重新运行测试。
terminal
bun test --watch

生命周期钩子

Bun 支持以下生命周期钩子:
钩子描述
beforeAll所有测试开始前执行一次
beforeEach每个测试开始前执行
afterEach每个测试结束后执行
afterAll所有测试完成后执行一次
这些钩子可在测试文件中定义,或放在通过 --preload 预加载的单独文件中。
terminal
bun test --preload ./setup.ts
完整文档见测试 > 生命周期

模拟

使用 mock 函数创建模拟函数。
https://mintcdn.com/ikxin/RzFFGbzo0-4huILA/icons/typescript.svg?fit=max&auto=format&n=RzFFGbzo0-4huILA&q=85&s=a3dffd2241f05776d3bd25171d0c5a79math.test.ts
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(),其行为相同。
https://mintcdn.com/ikxin/RzFFGbzo0-4huILA/icons/typescript.svg?fit=max&auto=format&n=RzFFGbzo0-4huILA&q=85&s=a3dffd2241f05776d3bd25171d0c5a79math.test.ts
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 支持快照测试。
https://mintcdn.com/ikxin/RzFFGbzo0-4huILA/icons/typescript.svg?fit=max&auto=format&n=RzFFGbzo0-4huILA&q=85&s=a3dffd2241f05776d3bd25171d0c5a79math.test.ts
// toMatchSnapshot 示例用法
import { test, expect } from "bun:test";

test("snapshot", () => {
  expect({ a: 1 }).toMatchSnapshot();
});
要更新快照,使用 --update-snapshots 标志。
terminal
bun test --update-snapshots
完整文档见测试 > 快照

UI 与 DOM 测试

Bun 兼容流行的 UI 测试库: 完整文档见测试 > DOM 测试

性能

Bun 的测试运行器非常快速。
运行 266 个 React SSR 测试,速度快于 Jest 打印版本号。

AI 代理集成

在使用 Bun 的测试运行器和 AI 编码助手时,你可以开启更安静的输出模式,以提高可读性,减少上下文噪音。此功能在保留重要失败信息的同时,最小化测试输出的详尽程度。

环境变量

设置以下任一环境变量即可启用适合 AI 的输出:
  • CLAUDECODE=1 - 适用于 Claude Code
  • REPL_ID=1 - 适用于 Replit
  • AGENT=1 - 通用 AI 代理标志

行为

检测到 AI 代理环境时:
  • 只详细显示测试失败信息
  • 隐藏通过、跳过及待办测试指示符
  • 保留统计摘要
terminal
# 示例:为 Claude Code 启用安静输出
CLAUDECODE=1 bun test

# 仍显示失败和摘要,隐藏通过测试的详细输出
此功能特别适合 AI 辅助开发流程,在减少输出量的同时保持对失败测试的可见性,提高上下文效率。

CLI 用法

bun test <patterns>

执行控制

--timeout
number
default:"5000"
设置每个测试的超时时间,单位为毫秒(默认 5000)
--rerun-each
number
每个测试文件重新运行 NUMBER 次,有助于捕捉某些错误
--concurrent
boolean
将所有测试视为 test.concurrent() 测试
--randomize
boolean
以随机顺序运行测试
--seed
number
设置测试随机化的随机种子
--bail
number
default:"1"
在出现 NUMBER 次失败后退出测试套件。如果不指定数字,默认为 1。
--max-concurrency
number
default:"20"
最大同时执行的测试数量(默认 20)

测试过滤

--todo
boolean
包含标记为 test.todo() 的测试
--test-name-pattern
string
只运行名称匹配给定正则表达式的测试。别名:-t

报告

--reporter
string
测试输出报告格式。可用选项:junit(需要 —reporter-outfile)、dots。默认:控制台输出。
--reporter-outfile
string
报告格式的输出文件路径(与 —reporter 一起使用时必需)
--dots
boolean
启用点状报告。—reporter=dots 的简写

覆盖率

--coverage
boolean
生成覆盖率报告
--coverage-reporter
string
default:"text"
text 和/或 lcov 格式报告覆盖率。默认 text
--coverage-dir
string
default:"coverage"
覆盖率文件的目录。默认 coverage

快照

--update-snapshots
boolean
更新快照文件。别名:-u

示例

运行所有测试文件:
terminal
bun test
运行所有文件名包含 “foo” 或 “bar” 的测试文件:
terminal
bun test foo bar
运行所有测试文件,只包含名称包含 “baz” 的测试:
terminal
bun test --test-name-pattern baz