核心工具链测试运行器
测试运行器
使用 bun:test 编写测试、模拟依赖并在 CI 中稳定执行
最后更新于
最小测试
import { describe, expect, test } from 'bun:test';
describe('sum', () => {
test('adds values', () => {
expect(2 + 3).toBe(5);
});
});bun test
bun test sum
bun test --watch
bun test --coverageBun 自动发现常见的 *.test.*、*_test.*、*.spec.* 和 *_spec.* 文件。
生命周期与异步测试
import { afterEach, beforeEach, expect, test } from 'bun:test';
let controller: AbortController;
beforeEach(() => {
controller = new AbortController();
});
afterEach(() => {
controller.abort();
});
test('loads data', async () => {
const response = await fetch('https://example.com', {
signal: controller.signal,
});
expect(response.ok).toBe(true);
});真实项目应模拟外部网络,保证测试可重复且不会产生费用或写入生产数据。
Mock 原则
bun:test 提供 mock()、spyOn() 和模块模拟。优先顺序:
- 纯函数直接测输入输出。
- 用依赖注入替换网络、时钟、随机数和数据库。
- 只有模块边界难以改造时才使用模块 mock。
- 每个测试后恢复状态,避免顺序依赖。
隔离、并行与 CI 分片
Bun 1.3.13 起提供面向大型测试套件的文件级隔离和并行能力:
# 本地发现跨文件状态泄漏
bun test --isolate
# CI 内按 CPU 并行;--parallel 会隐含 --isolate
bun test --parallel --coverage
# 三个独立 CI Job
bun test --shard=1/3
bun test --shard=2/3
bun test --shard=3/3数据库集成测试、固定端口和共享临时目录可能无法安全并行。为每个 Worker 分配独立数据库/schema、端口和临时目录,或把这组测试保留为串行任务。
覆盖率与不稳定测试
[test]
coverage = true
coverageReporter = ["text", "lcov"]
coverageDir = "./coverage"
coverageSkipTestFiles = true
coverageThreshold = 0.8阈值不达标时测试进程返回非零状态。覆盖率只能证明代码被执行,不能证明断言有效;关键安全、权限和迁移路径仍需明确场景。
bun test --randomize # 发现顺序依赖并记录 seed
bun test --seed 12345 # 重现顺序
bun test --retry 2 # 仅用于已知瞬态边界
bun test --rerun-each 20 # 主动暴露不稳定测试不要用无限重试掩盖确定性缺陷。CI 应记录失败 seed、分片和 Bun 版本。
给编码 Agent 的紧凑输出
AGENT=1 bun testBun 会隐藏通过测试的逐条噪声,但保留失败详情和摘要。安静输出不会改变退出码,也不能替代保存完整 CI 日志。
从 Jest 迁移
Bun 追求 Jest 兼容,但迁移仍应核对:
- 自定义 test environment 和 DOM 环境;
- 复杂 fake timers;
- Jest 专属 transformer;
- 原生扩展和依赖 Node.js loader 的设置;
- snapshot 路径与 CI 更新策略。
bun test --bailCI 中可用 --bail 快速失败,但本地排查时通常希望看到完整失败列表。