使用萬用字元模式有選擇地並行執行測試
設定萬用字元模式以決定來自哪些檔案的哪些測試並行執行
bunfig.toml 中的 concurrentTestGlob 選項會在檔名匹配萬用字元模式的檔案中並行執行測試。
專案結構
專案結構
my-project/
├── bunfig.toml
├── tests/
│ ├── unit/
│ │ ├── math.test.ts # 順序執行
│ │ └── utils.test.ts # 順序執行
│ └── integration/
│ ├── concurrent-api.test.ts # 並行執行
│ └── concurrent-database.test.ts # 並行執行
設定
設定 bunfig.toml,以並行執行帶有“concurrent-”字首的測試檔案:
bunfig.toml
[test]
# 並行執行所有以 "concurrent-" 開頭的測試檔案
concurrentTestGlob = "**/concurrent-*.test.ts"
測試檔案
單元測試(順序執行)
共享狀態或相依執行順序的測試應保持順序執行:
import { test, expect } from "bun:test";
// 這些測試預設順序執行
let sharedState = 0;
test("addition", () => {
sharedState = 5 + 3;
expect(sharedState).toBe(8);
});
test("uses previous state", () => {
// 該測試相依於前一個測試的狀態
expect(sharedState).toBe(8);
});
整合測試(並行執行)
匹配萬用字元模式的檔案中的測試自動並行執行:
import { test, expect } from "bun:test";
// 由於檔名匹配萬用字元模式,這些測試會自動並行執行。
// 在匹配 concurrentTestGlob 時,使用 test() 等同於 test.concurrent()。
// 每個測試都是獨立的,可以並行執行。
test("fetch user data", async () => {
const response = await fetch("/api/user/1");
expect(response.ok).toBe(true);
});
// 也可以顯式使用 test.concurrent() 標記為並行執行
test.concurrent("fetch posts", async () => {
const response = await fetch("/api/posts");
expect(response.ok).toBe(true);
});
// 也可以顯式使用 test.serial() 標記為順序執行
test.serial("fetch comments", async () => {
const response = await fetch("/api/comments");
expect(response.ok).toBe(true);
});
執行測試
terminal
# 執行所有測試 - concurrent-*.test.ts 檔案將並行執行
bun test
# 覆蓋設定:強制所有測試並行執行
# 注意:此選項會覆蓋 bunfig.toml,所有測試無視萬用字元都並行執行
bun test --concurrent
# 只執行單元測試(順序執行)
bun test tests/unit
# 只執行整合測試(由於萬用字元模式並行執行)
bun test tests/integration
優點
- 漸進式遷移:一次重新命名一個檔案,將其遷移到並行執行
- 組織清晰:檔名會告訴你該檔案中的測試如何執行
- 效能提升:獨立的整合測試並行執行環境完成得更快
- 安全性:單元測試在需要時保持序列執行
遷移策略
遷移現有測試到並行執行:
- 從相互獨立的整合測試開始 - 這些測試通常不會共享狀態
- 重新命名檔案以匹配 glob 模式:
mv api.test.ts concurrent-api.test.ts - 執行
bun test- 檢查競態條件以及不穩定或意外的失敗 - 逐個檔案繼續遷移穩定的測試
建議
- 使用描述性字首:
concurrent-、parallel-、async- - 將相關的順序測試放在同一目錄中
- 通過註釋說明某些測試必須保持順序執行的原因
- 在順序執行的檔案中使用
test.concurrent()進行細粒度控制 (在與concurrentTestGlob匹配的檔案中,普通的test()已會並行執行)
多個模式
concurrentTestGlob 也接受多個模式:
bunfig.toml
[test]
concurrentTestGlob = [
"**/integration/*.test.ts",
"**/e2e/*.test.ts",
"**/concurrent-*.test.ts"
]
匹配任意這些模式的檔案中的測試將並行執行:
- 所有
integration/目錄下的測試 - 所有
e2e/目錄下的測試 - 專案中任意位置所有以
concurrent-字首命名的測試檔案。