本指南演示如何使用 concurrentTestGlob 选项根据文件命名模式选择性地并发运行测试。
项目结构
sh
my-project/
├── bunfig.toml
├── tests/
│ ├── unit/
│ │ ├── math.test.ts # 顺序执行
│ │ └── utils.test.ts # 顺序执行
│ └── integration/
│ ├── concurrent-api.test.ts # 并发执行
│ └── concurrent-database.test.ts # 并发执行配置
配置你的 bunfig.toml 以并发运行带有 "concurrent-" 前缀的测试文件:
toml
[test]
# 并发运行所有带有 "concurrent-" 前缀的测试文件
concurrentTestGlob = "**/concurrent-*.test.ts"测试文件
单元测试(顺序执行)
当测试共享状态或有特定顺序要求时,顺序执行测试是好的选择:
ts
import { test, expect } from "bun:test";
// 这些测试默认顺序执行
let sharedState = 0;
test("加法", () => {
sharedState = 5 + 3;
expect(sharedState).toBe(8);
});
test("使用之前的状态", () => {
// 这个测试依赖于前一个测试的状态
expect(sharedState).toBe(8);
});集成测试(并发执行)
匹配 glob 模式的测试文件中的测试会自动并发运行:
ts
import { test, expect } from "bun:test";
// 由于文件名匹配 concurrentTestGlob,这些测试会自动并发运行
// 当文件匹配 concurrentTestGlob 时,使用 test() 等同于 test.concurrent()
// 每个测试都是独立的,可以并行运行
test("获取用户数据", async () => {
const response = await fetch("/api/user/1");
expect(response.ok).toBe(true);
});
// 也可以使用 test.concurrent() 显式标记为并发
test.concurrent("获取帖子", async () => {
const response = await fetch("/api/posts");
expect(response.ok).toBe(true);
});
// 也可以使用 test.serial() 显式标记为顺序执行
test.serial("获取评论", async () => {
const response = await fetch("/api/comments");
expect(response.ok).toBe(true);
});运行测试
bash
# 运行所有测试 - concurrent-*.test.ts 文件将并发运行
bun test
# 覆盖:强制所有测试并发运行
# 注意:这会覆盖 bunfig.toml 并并发运行所有测试,无论 glob 如何
bun test --concurrent
# 只运行单元测试(顺序执行)
bun test tests/unit
# 只运行集成测试(由于 glob 模式而并发运行)
bun test tests/integration优势
- 渐进式迁移:通过重命名文件逐个文件地迁移到并发测试
- 清晰的组织:文件命名约定指示执行模式
- 性能:集成测试并行运行更快
- 安全性:单元测试在需要时保持顺序执行
- 灵活性:通过重命名文件轻松更改执行模式
迁移策略
迁移现有测试到并发执行:
- 从独立的集成测试开始 - 这些通常不共享状态
- 重命名文件以匹配 glob 模式:
mv api.test.ts concurrent-api.test.ts - 验证测试仍然通过 - 运行
bun test确保没有竞态条件 - 监控共享状态问题 - 注意不稳定的测试或意外失败
- 继续增量迁移稳定的测试 - 不要急于迁移
提示
- 使用描述性前缀:
concurrent-、parallel-、async- - 将相关的顺序测试保持在同一目录中
- 用注释记录为什么某些测试必须保持顺序执行
- 使用
test.concurrent()在顺序文件中进行细粒度控制 (注意:在concurrentTestGlob匹配的文件中,普通的test()已经并发运行)
多个模式
你可以为不同的测试类别指定多个模式:
toml
[test]
concurrentTestGlob = [
"**/integration/*.test.ts",
"**/e2e/*.test.ts",
"**/concurrent-*.test.ts"
]此配置将在测试匹配任何这些模式时并发运行测试:
integration/目录中的所有测试e2e/目录中的所有测试- 项目中任何带有
concurrent-前缀的测试