テストランナーは、次のライフサイクルフックをサポートしています。これは、テストフィクスチャの読み込み、データのモック、テスト環境の設定に役立ちます。
| フック | 説明 |
|---|---|
beforeAll | すべてのテストの前に 1 回実行します。 |
beforeEach | 各テストの前に実行します。 |
afterEach | 各テストの後に実行します。 |
afterAll | すべてのテストの後に 1 回実行します。 |
onTestFinished | 単一のテストの完了後に実行します(すべての afterEach の後)。 |
テストごとのセットアップとティアダウン
beforeEach と afterEach を使用して、テストごとのセットアップとティアダウンロジックを実行します。
ts
import { beforeEach, afterEach, test } from "bun:test";
beforeEach(() => {
console.log("テストを実行中。");
});
afterEach(() => {
console.log("テスト完了。");
});
// テスト...
test("テスト例", () => {
// このテストは、前に beforeEach が実行され、後に afterEach が実行されます
});スコープごとのセットアップとティアダウン
beforeAll と afterAll を使用して、スコープごとのセットアップとティアダウンロジックを実行します。スコープは、フックが定義されている場所によって決定されます。
describe ブロックへのスコープ
フックを特定の describe ブロックにスコープするには。
ts
import { describe, beforeAll, afterAll, test } from "bun:test";
describe("テストグループ", () => {
beforeAll(() => {
// この describe ブロックのセットアップ
console.log("テストグループのセットアップ");
});
afterAll(() => {
// この describe ブロックのティアダウン
console.log("テストグループのティアダウン");
});
test("テスト 1", () => {
// テスト実装
});
test("テスト 2", () => {
// テスト実装
});
});テストファイルへのスコープ
フックをテストファイル全体にスコープするには。
ts
import { describe, beforeAll, afterAll, test } from "bun:test";
beforeAll(() => {
// ファイル全体のセットアップ
console.log("テストファイルのセットアップ");
});
afterAll(() => {
// ファイル全体のティアダウン
console.log("テストファイルのティアダウン");
});
describe("テストグループ", () => {
test("テスト 1", () => {
// テスト実装
});
});onTestFinished
onTestFinished を使用して、単一のテストの完了後にコールバックを実行します。これは、すべての afterEach フックの後に実行されます。
ts
import { test, onTestFinished } from "bun:test";
test("テスト後にクリーンアップ", () => {
onTestFinished(() => {
// すべての afterEach フックの後に実行
console.log("テスト完了");
});
});並行テストではサポートされていません。代わりに test.serial を使用してください。
グローバルセットアップとティアダウン
フックをマルチファイルのテスト実行全体にスコープするには、フックを別のファイルで定義します。
ts
import { beforeAll, afterAll } from "bun:test";
beforeAll(() => {
// グローバルセットアップ
console.log("グローバルテストセットアップ");
// データベース接続の初期化、サーバーの起動など
});
afterAll(() => {
// グローバルティアダウン
console.log("グローバルテストティアダウン");
// データベース接続のクローズ、サーバーの停止など
});次に、--preload を使用して、テストファイルの前にセットアップスクリプトを実行します。
bash
bun test --preload ./setup.tsテストを実行するたびに --preload と入力しないようにするには、bunfig.toml に追加できます。
toml
[test]
preload = ["./setup.ts"]実用的な例
データベースセットアップ
ts
import { beforeAll, afterAll, beforeEach, afterEach } from "bun:test";
import { createConnection, closeConnection, clearDatabase } from "./db";
let connection;
beforeAll(async () => {
// テストデータベースに接続
connection = await createConnection({
host: "localhost",
database: "test_db",
});
});
afterAll(async () => {
// データベース接続をクローズ
await closeConnection(connection);
});
beforeEach(async () => {
// 各テストのためにクリーンなデータベースで開始
await clearDatabase(connection);
});API サーバーセットアップ
ts
import { beforeAll, afterAll } from "bun:test";
import { startServer, stopServer } from "./server";
let server;
beforeAll(async () => {
// テストサーバーを起動
server = await startServer({
port: 3001,
env: "test",
});
});
afterAll(async () => {
// テストサーバーを停止
await stopServer(server);
});モックセットアップ
ts
import { beforeEach, afterEach } from "bun:test";
import { mock } from "bun:test";
beforeEach(() => {
// 一般的なモックを設定
mock.module("./api-client", () => ({
fetchUser: mock(() => Promise.resolve({ id: 1, name: "Test User" })),
createUser: mock(() => Promise.resolve({ id: 2 })),
}));
});
afterEach(() => {
// 各テスト後にすべてのモックをクリア
mock.restore();
});非同期ライフサイクルフック
すべてのライフサイクルフックは非同期関数をサポートします。
ts
import { beforeAll, afterAll, test } from "bun:test";
beforeAll(async () => {
// 非同期セットアップ
await new Promise(resolve => setTimeout(resolve, 100));
console.log("非同期セットアップ完了");
});
afterAll(async () => {
// 非同期ティアダウン
await new Promise(resolve => setTimeout(resolve, 100));
console.log("非同期ティアダウン完了");
});
test("非同期テスト", async () => {
// beforeAll の完了を待機します
await expect(Promise.resolve("test")).resolves.toBe("test");
});ネストされたフック
フックはネストでき、適切な順序で実行されます。
ts
import { describe, beforeAll, beforeEach, afterEach, afterAll, test } from "bun:test";
beforeAll(() => console.log("ファイル beforeAll"));
afterAll(() => console.log("ファイル afterAll"));
describe("外部 describe", () => {
beforeAll(() => console.log("外部 beforeAll"));
beforeEach(() => console.log("外部 beforeEach"));
afterEach(() => console.log("外部 afterEach"));
afterAll(() => console.log("外部 afterAll"));
describe("内部 describe", () => {
beforeAll(() => console.log("内部 beforeAll"));
beforeEach(() => console.log("内部 beforeEach"));
afterEach(() => console.log("内部 afterEach"));
afterAll(() => console.log("内部 afterAll"));
test("ネストされたテスト", () => {
console.log("テスト実行中");
});
});
});txt
// 出力順序:
// ファイル beforeAll
// 外部 beforeAll
// 内部 beforeAll
// 外部 beforeEach
// 内部 beforeEach
// テスト実行中
// 内部 afterEach
// 外部 afterEach
// 内部 afterAll
// 外部 afterAll
// ファイル afterAllエラーハンドリング
ライフサイクルフックがエラーをスローすると、テスト実行に影響します。
ts
import { beforeAll, test } from "bun:test";
beforeAll(() => {
// これがスローされると、このスコープのすべてのテストがスキップされます
throw new Error("セットアップに失敗しました");
});
test("このテストはスキップされます", () => {
// beforeAll が失敗したため、これは実行されません
});より良いエラーハンドリングのために。
ts
import { beforeAll, test, expect } from "bun:test";
beforeAll(async () => {
try {
await setupDatabase();
} catch (error) {
console.error("データベースセットアップに失敗しました:", error);
throw error; // テストスイートを失敗させるために再スロー
}
});ベストプラクティス
フックをシンプルに保つ
ts
// 良い:シンプルで焦点を絞ったセットアップ
beforeEach(() => {
clearLocalStorage();
resetMocks();
});
// 避ける:フック内の複雑なロジックはテストのデバッグを困難にします
beforeEach(async () => {
// 複雑なロジックが多すぎるとテストのデバッグが困難になります
const data = await fetchComplexData();
await processData(data);
await setupMultipleServices(data);
});適切なスコープを使用する
ts
// 良い:共有リソースのファイルレベルセットアップ
beforeAll(async () => {
await startTestServer();
});
// 良い:テスト固有の状態のテストレベルセットアップ
beforeEach(() => {
user = createTestUser();
});リソースをクリーンアップする
ts
import { afterAll, afterEach } from "bun:test";
afterEach(() => {
// 各テスト後にクリーンアップ
document.body.innerHTML = "";
localStorage.clear();
});
afterAll(async () => {
// 高価なリソースをクリーンアップ
await closeDatabase();
await stopServer();
});