Skip to content

本指南演示如何使用 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

優勢

  1. 漸進式遷移:通過重命名文件逐個文件地遷移到並發測試
  2. 清晰的組織:文件命名約定指示執行模式
  3. 性能:集成測試並行運行更快
  4. 安全性:單元測試在需要時保持順序執行
  5. 靈活性:通過重命名文件輕松更改執行模式

遷移策略

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

  1. 從獨立的集成測試開始 - 這些通常不共享狀態
  2. 重命名文件以匹配 glob 模式mv api.test.ts concurrent-api.test.ts
  3. 驗證測試仍然通過 - 運行 bun test 確保沒有競態條件
  4. 監控共享狀態問題 - 注意不穩定的測試或意外失敗
  5. 繼續增量遷移穩定的測試 - 不要急於遷移

提示

  • 使用描述性前綴concurrent-parallel-async-
  • 將相關的順序測試保持在同一目錄中
  • 用注釋記錄為什麼某些測試必須保持順序執行
  • 使用 test.concurrent() 在順序文件中進行細粒度控制 (注意:在 concurrentTestGlob 匹配的文件中,普通的 test() 已經並發運行)

多個模式

你可以為不同的測試類別指定多個模式:

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

此配置將在測試匹配任何這些模式時並發運行測試:

  • integration/ 目錄中的所有測試
  • e2e/ 目錄中的所有測試
  • 項目中任何帶有 concurrent- 前綴的測試

Bun學習網由www.bunjs.com.cn整理維護