執行環境套件管理器打包器測試執行器程式碼檢查格式化指南參考部落格意見回饋

使用萬用字元模式有選擇地並行執行測試

設定萬用字元模式以決定來自哪些檔案的哪些測試並行執行

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"

測試檔案

單元測試(順序執行)

共享狀態或相依執行順序的測試應保持順序執行:

tests/unit/math.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);
});

整合測試(並行執行)

匹配萬用字元模式的檔案中的測試自動並行執行:

tests/integration/concurrent-api.test.ts
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

優點

  1. 漸進式遷移:一次重新命名一個檔案,將其遷移到並行執行
  2. 組織清晰:檔名會告訴你該檔案中的測試如何執行
  3. 效能提升:獨立的整合測試並行執行環境完成得更快
  4. 安全性:單元測試在需要時保持序列執行

遷移策略

遷移現有測試到並行執行:

  1. 從相互獨立的整合測試開始 - 這些測試通常不會共享狀態
  2. 重新命名檔案以匹配 glob 模式:mv api.test.ts concurrent-api.test.ts
  3. 執行 bun test - 檢查競態條件以及不穩定或意外的失敗
  4. 逐個檔案繼續遷移穩定的測試

建議

  • 使用描述性字首:concurrent-、parallel-、async-
  • 將相關的順序測試放在同一目錄中
  • 通過註釋說明某些測試必須保持順序執行的原因
  • 在順序執行的檔案中使用 test.concurrent() 進行細粒度控制 (在與 concurrentTestGlob 匹配的檔案中,普通的 test() 已會並行執行)

多個模式

concurrentTestGlob 也接受多個模式:

bunfig.toml
[test]
concurrentTestGlob = [
  "**/integration/*.test.ts",
  "**/e2e/*.test.ts",
  "**/concurrent-*.test.ts"
]

匹配任意這些模式的檔案中的測試將並行執行:

  • 所有 integration/ 目錄下的測試
  • 所有 e2e/ 目錄下的測試
  • 專案中任意位置所有以 concurrent- 字首命名的測試檔案。