測試執行器
Bun 的快速內建 Jest 相容測試執行器,支援 TypeScript、生命週期鉤子、模擬和監視模式
Bun 自帶一個快速且與 Jest 相容的測試執行器。測試在 Bun 執行環境中執行,並支援以下功能。
- TypeScript 和 JSX
- 生命週期鉤子
- 快照測試
- UI 與 DOM 測試
- 使用
--watch的監視模式 - 使用
--preload的指令碼預載入
執行測試
bun test
你可以使用類似 Jest 的 API,以 JavaScript 或 TypeScript 編寫測試。請參閱編寫測試。
import { expect, test } from "bun:test";
test("2 + 2", () => {
expect(2 + 2).toBe(4);
});
測試執行器會遞迴搜尋工作目錄中符合以下模式的檔案:
*.test.{js|jsx|ts|tsx|mjs|cjs|mts|cts}*_test.{js|jsx|ts|tsx|mjs|cjs|mts|cts}*.spec.{js|jsx|ts|tsx|mjs|cjs|mts|cts}*_spec.{js|jsx|ts|tsx|mjs|cjs|mts|cts}
若要篩選要執行的_測試檔案_,請向 bun test 傳遞其他位置引數。路徑與任一篩選條件匹配的測試檔案都會執行。篩選條件通常是檔名或目錄名;目前尚不支援 glob 模式。
bun test <filter> <filter> ...
如果要根據 測試名稱 過濾,使用 -t/--test-name-pattern 標誌。
# 執行名稱中含 "addition" 的所有測試或測試套件
bun test --test-name-pattern addition
若要執行特定檔案,確保路徑以 ./ 或 / 開頭,以區別於篩選名。
bun test ./test/specific-file.test.ts
預設情況下,測試執行器會在單個行程中執行所有測試:它會載入所有 --preload 指令碼(請參閱生命週期),然後在一個共享全域性環境中執行每個檔案。傳入 --parallel 可將檔案分散到各個 CPU 核心上執行。如果測試失敗,測試執行器會以非零退出程式碼退出。
CI/CD 整合
bun test 支援多種 CI/CD 整合方案。
GitHub Actions
bun test 會自動檢測其是否在 GitHub Actions 中執行,並直接向控制台輸出 GitHub Actions 註釋。
無需額外設定,只需在工作流程中安裝 bun 並執行 bun test。
如何在 GitHub Actions 工作流程中安裝 bun
要在 GitHub Actions 工作流程中使用 bun test,新增如下步驟:
jobs:
build:
name: build-app
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install bun
uses: oven-sh/setup-bun@v2
- name: Install dependencies # (假設你的專案有相依)
run: bun install # 如果喜歡,也可以用 npm/yarn/pnpm 代替
- name: Run tests
run: bun test
JUnit XML 報告(GitLab 等)
要寫入 JUnit XML 報告,請將 --reporter=junit 與 --reporter-outfile 一起傳入。
bun test --reporter=junit --reporter-outfile=./bun.xml
bun test 仍會像往常一樣寫入 stdout/stderr,並在執行結束時將 JUnit XML 報告寫入指定路徑。
JUnit XML 是 CI/CD 管道中報告測試結果的流行格式。
超時設定
使用 --timeout 標誌指定每個測試的超時時間,單位為毫秒。如果測試超時,Bun 會將其標記為失敗。預設值為 5000。
# 預設值是 5000
bun test --timeout 20
並行測試執行
要跨 CPU 核執行測試檔案,請參閱 --parallel。以下標誌控制檔案_內部_測試的並行性。
預設情況下,Bun 會在每個測試檔案中按順序執行所有測試。並行執行會並行執行非同步測試,從而加快包含相互獨立測試的測試套件。
--concurrent 標誌
使用 --concurrent 標誌,實現各測試檔案內部的所有測試並行執行:
bun test --concurrent
啟用此標誌後,除非測試標記為 test.serial,否則所有測試都會並行執行。
--max-concurrency 標誌
用 --max-concurrency 標誌控制最大並行測試數量:
# 限制最大並行測試為 4 個
bun test --concurrent --max-concurrency 4
# 預設值是 20
bun test --concurrent
此限制有助於在執行大量並行測試時防止資源耗盡。預設值為 20。
test.concurrent
單獨標記測試為並行執行,即使未使用 --concurrent 也能並行執行:
import { test, expect } from "bun:test";
// 這些測試相互並行執行
test.concurrent("concurrent test 1", async () => {
await fetch("/api/endpoint1");
expect(true).toBe(true);
});
test.concurrent("concurrent test 2", async () => {
await fetch("/api/endpoint2");
expect(true).toBe(true);
});
// 此測試順序執行
test("sequential test", () => {
expect(1 + 1).toBe(2);
});
test.serial
即使啟用 --concurrent 標誌,也強制測試順序執行:
import { test, expect } from "bun:test";
let sharedState = 0;
// 這些測試必須順序執行
test.serial("first serial test", () => {
sharedState = 1;
expect(sharedState).toBe(1);
});
test.serial("second serial test", () => {
// 相依前一個測試
expect(sharedState).toBe(1);
sharedState = 2;
});
// 如果啟用 --concurrent,此測試可並行執行
test("independent test", () => {
expect(true).toBe(true);
});
// 測試限定符鏈式呼叫
test.failing.each([1, 2, 3])("chained qualifiers %d", input => {
expect(input).toBe(0); // 對每個輸入,該測試預期失敗
});
重試失敗的測試
使用 --retry 標誌自動重試失敗的測試,最多重試指定次數。如果測試失敗後在後續嘗試中通過,Bun 會將其報告為通過。
bun test --retry 3
每個測試可以通過 { retry: N } 設定覆蓋全域性的 --retry 值:
// 使用全域性 --retry 值
test("uses global retry", () => {
/* ... */
});
// 使用自己的重試次數覆蓋 --retry
test("custom retry", { retry: 1 }, () => {
/* ... */
});
你也可以在 bunfig.toml 中設定:
[test]
retry = 3
重新執行測試
使用 --rerun-each 標誌多次執行每個測試。這有助於發現不穩定或非確定性的測試失敗。
bun test --rerun-each 100
隨機化測試執行順序
使用 --randomize 標誌以隨機順序執行測試,有助於發現相依共享狀態或執行順序的測試。
bun test --randomize
使用 --randomize 時,Bun 會在測試摘要中顯示用於隨機化的種子:
bun test --randomize
# ... 測試輸出 ...
--seed=12345
2 pass
8 fail
Ran 10 tests across 2 files. [50.00ms]
使用 --seed 實現可復現的隨機順序
使用 --seed 標誌指定隨機化種子,以便在除錯相依執行順序的失敗測試時復現相同的測試順序。
# 復現之前的隨機執行順序
bun test --seed 123456
--seed 標誌會隱式啟用 --randomize,因此無需同時指定這兩個標誌。相同的種子始終會產生相同的測試執行順序。
失敗即停止 --bail
使用 --bail 標誌,在測試失敗達到指定次數後中止測試執行。預設情況下,Bun 會執行所有測試並報告所有失敗,但在 CI 中,提前停止測試並減少 CPU 使用量可能更為合適。
# 發生 1 次失敗即停止
bun test --bail
# 發生 10 次失敗即停止
bun test --bail=10
監視模式
與 bun run 類似,bun test 接受 --watch 標誌,以監視更改並重新執行測試。
bun test --watch
生命週期鉤子
Bun 支援以下生命週期鉤子:
| 鉤子 | 描述 |
|---|---|
beforeAll | 所有測試開始前執行一次 |
beforeEach | 每個測試開始前執行 |
afterEach | 每個測試結束後執行 |
afterAll | 所有測試完成後執行一次 |
在測試檔案中定義鉤子,或在使用 --preload 標誌預載入的單獨檔案中定義鉤子。
bun test --preload ./setup.ts
請參閱生命週期。
模擬
使用 mock 函式建立模擬函式。
import { test, expect, mock } from "bun:test";
const random = mock(() => Math.random());
test("random", () => {
const val = random();
expect(val).toBeGreaterThan(0);
expect(random).toHaveBeenCalled();
expect(random).toHaveBeenCalledTimes(1);
});
或者使用 jest.fn();其行為完全相同。
import { test, expect, mock } from "bun:test"; // [!code --]
import { test, expect, jest } from "bun:test"; // [!code ++]
const random = mock(() => Math.random()); // [!code --]
const random = jest.fn(() => Math.random()); // [!code ++]
請參閱模擬。
快照測試
bun test 支援快照測試。
// toMatchSnapshot 範例用法
import { test, expect } from "bun:test";
test("snapshot", () => {
expect({ a: 1 }).toMatchSnapshot();
});
要更新快照,請使用 --update-snapshots 標誌。
bun test --update-snapshots
請參閱快照。
UI 與 DOM 測試
Bun 相容流行的 UI 測試庫:
請參閱 DOM 測試。
大型程式碼庫
對於包含數千個測試檔案的測試套件,bun test 提供了多個可組合使用的調優選項:工作行程、隔離級別、跨機器分片,以及基於執行時長的排程。並行與隔離測試執行深入介紹了每一項。以下按大致收益順序介紹它們的配合方式:
1. 使用每個核心:--parallel。 每個核心使用一個工作行程,檔案一次分配一個。
2. 決定需要多少隔離。 --parallel 會為每個檔案提供全新的全域性環境,這是安全的預設設定,也是 Jest/Vitest 的做法。如果檔案之間不會洩漏狀態(它們在共享同一個全域性環境的普通 bun test 下已經可以通過),--parallel --no-isolate 可讓每個工作行程只評估一次匯入和預載入指令碼,而不是每個檔案評估一次。對於由許多小檔案組成的測試套件,這通常是最大的效能提升。請參閱對比方式。
3. 跨機器拆分:--shard=i/n。 確定性拆分,無需協調器。每個 CI 作業執行一個分片,而每個分片仍會在本地使用 --parallel。
4. 按耗時而非數量均衡:--timings。 有了記錄的耗時資料後,Bun 會拆分分片,使每個分片的總耗時大致相同。拆分採用最長處理時間優先的方式,同時將路徑相鄰的檔案放在一起,以保持工作行程的模組快取處於預熱狀態。每個工作行程會先啟動耗時最長的檔案,空閒工作行程則會接手剩餘檔案中耗時最長的檔案。這樣,偶然最後啟動的某個長檔案就不會拖慢整個執行過程。
5. 自動保持耗時資料最新:--update-timings。 每個分片會寫入其執行檔案的耗時;下一次執行會讀取所有這些資料。在 GitHub Actions 中,看起來如下:
jobs:
test:
strategy:
matrix:
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install
# last successful run's per-shard timings (nothing on the very first run)
- uses: actions/cache/restore@v4
with:
path: .bun-test-timings
key: bun-test-timings-${{ github.run_id }}
restore-keys: bun-test-timings-
- run: |
bun test --parallel --shard=${{ matrix.shard }}/4 --update-timings \
--timings=.bun-test-timings/next/${{ matrix.shard }}.json \
$(ls .bun-test-timings/*.json 2>/dev/null | sed 's/^/--timings=/')
- uses: actions/upload-artifact@v4
with:
name: timings-${{ matrix.shard }}
path: .bun-test-timings/next/${{ matrix.shard }}.json
save-timings:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
pattern: timings-*
path: .bun-test-timings
merge-multiple: true
- uses: actions/cache/save@v4
with:
path: .bun-test-timings
key: bun-test-timings-${{ github.run_id }}
每個分片必須讀取相同的一組耗時檔案,這樣各分片的耗時才能彙總為整個測試套件的耗時。因此,一次執行會讀取上次執行的檔案(從快取中恢復),並將自身的檔案寫入其他仍在執行的同級分片無法讀取的位置(如上方的 next/)。如果第 2 步適用於你,請在 bun test 命令中新增 --no-isolate。
6. 在檔案內部:test.concurrent 適用於將大部分時間花在等待上的 I/O 密集型測試。
效能
Bun 的測試執行器非常快速。

AI 代理整合
當你將 Bun 的測試執行器與 AI 程式設計助手結合使用時,可以啟用更安靜的輸出,在保留失敗詳情的同時去除其餘噪音。
環境變數
設定以下任一環境變數即可啟用適合 AI 的輸出:
CLAUDECODE=1- 適用於 Claude CodeREPL_ID=1- 適用於 ReplitAGENT=1- 通用 AI 代理標誌
行為
當 Bun 檢測到 AI 代理環境時:
- 只詳細顯示測試失敗資訊
- 隱藏通過、跳過及待辦測試指示符
- 保留統計摘要
# 範例:為 Claude Code 啟用安靜輸出
CLAUDECODE=1 bun test
# 仍顯示失敗和摘要,隱藏通過測試的詳細輸出
CLI 用法
bun test <patterns>
執行控制
--timeoutnumberdefault 5000設定每個測試的超時時間,單位為毫秒(預設 5000)
--rerun-eachnumber重新執行每個測試檔案 NUMBER 次,以幫助發現某些錯誤
--retrynumber最多重試失敗的測試 NUMBER 次。每個測試的 { retry: N } 會覆蓋此標誌
--concurrentboolean將所有測試視為 test.concurrent() 測試
--randomizeboolean以隨機順序執行測試
--seednumber設定測試隨機化的隨機種子
--bailnumber失敗 NUMBER 次後退出測試套件。如果不指定數字,則預設為 1
--max-concurrencynumberdefault 20最大同時執行的測試數量(預設 20)
測試過濾
--todoboolean包含標記為 test.todo() 的測試
--test-name-patternstring只執行名稱匹配給定正規表示式的測試。別名:-t
報告
--reporterstring測試輸出報告格式。可用選項:junit(需要 --reporter-outfile)、dots。預設:控制台輸出。
--reporter-outfilestring報告格式的輸出檔案路徑(與 --reporter=junit 一起使用時必需)
--dotsboolean啟用點狀報告。--reporter=dots 的簡寫
覆蓋率
--coverageboolean生成覆蓋率報告
--coverage-reporterstringdefault text以 text 和/或 lcov 格式報告覆蓋率。預設 text
--coverage-dirstringdefault coverage覆蓋率檔案的目錄。預設 coverage
快照
--update-snapshotsboolean更新快照檔案。別名:-u
範例
執行所有測試檔案:
bun test
執行所有檔名包含 "foo" 或 "bar" 的測試檔案:
bun test foo bar
執行所有測試檔案,僅包含名稱中含有 "baz" 的測試:
bun test --test-name-pattern baz