bun test は Bun のランタイムと深く統合されています。これが bun test を高速で簡単に使用する理由の一部です。
環境変数
NODE_ENV
bun test は、環境または .env ファイルですでに設定されていない限り、$NODE_ENV を自動的に "test" に設定します。これは、ほとんどのテストランナーの標準的な動作であり、一貫したテスト動作を確保するのに役立ちます。
import { test, expect } from "bun:test";
test("NODE_ENV は test に設定される", () => {
expect(process.env.NODE_ENV).toBe("test");
});これを明示的に設定して上書きできます。
NODE_ENV=development bun testTZ(タイムゾーン)
デフォルトでは、すべての bun test 実行は、TZ 環境変数で上書きされない限り、UTC(Etc/UTC)をタイムゾーンとして使用します。これにより、異なる開発環境間で一貫した日付と時刻の動作が確保されます。
import { test, expect } from "bun:test";
test("デフォルトでタイムゾーンは UTC", () => {
const date = new Date();
expect(date.getTimezoneOffset()).toBe(0);
});特定のタイムゾーンでテストするには。
TZ=America/New_York bun testテストタイムアウト
各テストには、明示的に上書きされない場合、デフォルトで 5000 ミリ秒(5 秒)のタイムアウトがあります。このタイムアウトを超えたテストは失敗としてマークされます。
グローバルタイムアウト
--timeout フラグを使用して、グローバルにタイムアウトを変更します。
bun test --timeout 10000 # 10 秒テストごとのタイムアウト
テスト関数の 3 番目のパラメータとして、テストごとにタイムアウトを設定します。
import { test, expect } from "bun:test";
test("高速テスト", () => {
expect(1 + 1).toBe(2);
}, 1000); // 1 秒タイムアウト
test("低速テスト", async () => {
await new Promise(resolve => setTimeout(resolve, 8000));
}, 10000); // 10 秒タイムアウト無制限タイムアウト
0 または Infinity を使用してタイムアウトを無効にします。
test("タイムアウトなしのテスト", async () => {
// このテストは無制限に実行できます
await someVeryLongOperation();
}, 0);エラーハンドリング
未処理のエラー
bun test は、テスト間で発生する未処理の Promise 拒否とエラーを追跡します。このようなエラーが発生した場合、すべてのテストに合格していても、最終的な終了コードは 0 以外(具体的には、そのようなエラーの数)になります。
これにより、そうでなければ見逃される可能性のある非同期コードのエラーを検出するのに役立ちます。
import { test } from "bun:test";
test("テスト 1", () => {
// このテストは合格
expect(true).toBe(true);
});
// このエラーはテスト外で発生
setTimeout(() => {
throw new Error("未処理のエラー");
}, 0);
test("テスト 2", () => {
// このテストも合格
expect(true).toBe(true);
});
// 未処理のエラーのため、テスト実行は 0 以外の終了コードで失敗しますPromise 拒否
未処理の Promise 拒否もキャッチされます。
import { test } from "bun:test";
test("合格テスト", () => {
expect(1).toBe(1);
});
// これによりテスト実行が失敗します
Promise.reject(new Error("未処理の拒否"));カスタムエラーハンドリング
テストセットアップでカスタムエラーハンドラーを設定できます。
process.on("uncaughtException", error => {
console.error("キャッチされない例外:", error);
process.exit(1);
});
process.on("unhandledRejection", (reason, promise) => {
console.error("未処理の拒否:", promise, "理由:", reason);
process.exit(1);
});CLI フラグ統合
いくつかの Bun CLI フラグを bun test と一緒に使用して、その動作を変更できます。
メモリ使用量
# テストランナー VM のメモリ使用量を削減
bun test --smolデバッグ
# デバッガーをテストランナープロセスにアタッチ
bun test --inspect
bun test --inspect-brkモジュール読み込み
# テストファイルの前にスクリプトを実行(グローバルセットアップ/モックに便利)
bun test --preload ./setup.ts
# コンパイル時定数を設定
bun test --define "process.env.API_URL='http://localhost:3000'"
# カスタムローダーを設定
bun test --loader .special:special-loader
# 異なる tsconfig を使用
bun test --tsconfig-override ./test-tsconfig.json
# モジュール解決用の package.json 条件を設定
bun test --conditions development
# テスト用の環境変数を読み込む
bun test --env-file .env.testインストール関連のフラグ
# テスト実行中のネットワークリクエストまたは自動インストールに影響
bun test --prefer-offline
bun test --frozen-lockfileウォッチとホットリロード
ウォッチモード
--watch フラグを使用して bun test を実行すると、テストランナーはファイルの変更を監視し、影響を受けたテストを再実行します。
bun test --watchテストランナーは、どのテストを再実行するかについて賢明です。
import { add } from "./math.js";
import { test, expect } from "bun:test";
test("加算", () => {
expect(add(2, 3)).toBe(5);
});math.js を変更すると、すべてのテストではなく math.test.ts のみが再実行されます。
ホットリロード
--hot フラグは、実行間で状態を保持しようとするより積極的な類似の機能を提供します。
bun test --hotほとんどのテストシナリオでは、より良いテスト実行間の分離を提供するため、--watch が推奨オプションです。
グローバル変数
次のグローバルは、インポートなしでテストファイルで自動的に利用可能です(必要に応じて bun:test からインポートもできます)。
// これらすべてがグローバルで利用可能
test("グローバルテスト関数", () => {
expect(true).toBe(true);
});
describe("グローバル describe", () => {
beforeAll(() => {
// グローバル beforeAll
});
it("グローバル it 関数", () => {
// it は test のエイリアス
});
});
// Jest 互換性
jest.fn();
// Vitest 互換性
vi.fn();必要に応じて、明示的にインポートすることもできます。
import { test, it, describe, expect, beforeAll, beforeEach, afterAll, afterEach, jest, vi } from "bun:test";プロセス統合
終了コード
bun test は標準の終了コードを使用します。
0: すべてのテストに合格し、未処理のエラーなし1: テスト失敗が発生>1: 未処理のエラー数(テストに合格していても)
シグナルハンドリング
テストランナーは一般的なシグナルを適切に処理します。
# テスト実行を正常に停止
kill -SIGTERM <test-process-pid>
# テスト実行を即座に停止
kill -SIGKILL <test-process-pid>環境検出
Bun は特定の環境を自動的に検出し、動作を調整します。
// GitHub Actions 検出
if (process.env.GITHUB_ACTIONS) {
// Bun は自動的に GitHub Actions アノテーションを出力
}
// CI 検出
if (process.env.CI) {
// CI 環境のために特定の動作が調整される場合があります
}パフォーマンスの考慮事項
単一プロセス
テストランナーは、デフォルトですべてのテストを単一のプロセスで実行します。これにより、以下が提供されます。
- より高速な起動 - 複数のプロセスを生成する必要がありません
- 共有メモリ - 効率的なリソース使用
- シンプルなデバッグ - 1 つのプロセスですべてのテスト
ただし、これは以下を意味します。
- テストはグローバル状態を共有します(クリーンアップするにはライフサイクルフックを使用)
- 1 つのテストのクラッシュが他のテストに影響する可能性があります
- 個々のテストの真の並列化はありません
メモリ管理
# メモリ使用量を監視
bun test --smol # メモリフットプリントを削減
# 大規模なテストスイートの場合、ファイルを分割することを検討
bun test src/unit/
bun test src/integration/テスト分離
テストは同じプロセスで実行されるため、適切なクリーンアップを確保します。
import { afterEach } from "bun:test";
afterEach(() => {
// グローバル状態をクリーンアップ
global.myGlobalVar = undefined;
delete process.env.TEST_VAR;
// 必要に応じてモジュールをリセット
jest.resetModules();
});