testing-best-practices について
Playwright、統合テスト、ユニットテストの選択とテストデータの管理を支援するテストスキルです。分離され、自動削除される Neon ブランチでのテスト実行方法も説明します。
主な機能
- 01テスト種別の選択ガイド
- 02Playwright・統合・ユニットテストのパターン
- 03一時 Neon ブランチでのテスト実行
- 04テストスイートごとのデータ分離
- 05デバッグ用コマンドと成果物の説明
活用シーン
- 01機能に適したテスト層の選択
- 02分離されたデータベース状態でのテスト実行
- 03Playwright やユニットテストの失敗調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ andrelandgraf/ fullstackrecipes --skill testing-best-practicesインストール後、Claude Code で/testing-best-practicesを入力して読み込まれたか確認します。
詳細
テストのベストプラクティス
適切なテストの種類を選び、スイートごとにデータを分離し、破棄可能な Neon ブランチに対して実行します。
前提条件
まず、次のセットアップ手順を完了してください。
- Playwright によるブラウザテスト
- 統合テスト
- Bun によるユニットテスト
テストの種類を選ぶ
「ユーザーはこれが動作することをどのように確認するだろうか?」と考え、該当する最も高い階層を選びます。
- Playwright(デフォルト)— UI 操作、視覚的なフィードバック、フォームの検証、複数ステップのフロー、保護されたルート、アクセシビリティ。
- 統合テスト — API レスポンス(ステータス、JSON の形式)、操作後の DB の状態、UI を介さないサーバーのロジック、または Playwright が遅すぎる、複雑すぎる場合。
- ユニットテスト — 複雑なロジック、多くのエッジケースを含む純粋関数、または外部依存のない型の絞り込み/アサーション。
実行
すべてのテストは、1 時間後に自動削除される、スキーマのみの分離された Neon ブランチに対して実行されます。
bun run test # all tests
bun run test:playwright # browser only
bun run test:integration # integration only
bun run test:unit # unit only
フォルダー構成
ユニットテストは対象のコードと同じ場所に配置し、Playwright と統合テストは tests/ 以下に配置します。
src/lib/<domain>/<file>.test.ts # unit (co-located)
tests/integration/<feature>.test.ts
tests/playwright/<feature>.spec.ts
tests/playwright/lib/ # Playwright helpers
テストの作成
Playwright の spec:
import { test, expect } from "@playwright/test";
test.describe("Feature Name", () => {
test("should do expected behavior", async ({ page }) => {
await page.goto("/feature");
});
});
統合テスト — HTTP 経由ではなく、ルートハンドラーを直接インポートします。
import { describe, it, expect } from "bun:test";
import { GET } from "@/app/api/feature/route";
describe("GET /api/feature", () => {
it("returns expected response", async () => {
const response = await GET();
expect(response.status).toBe(200);
const data = await response.json();
expect(data.value).toBeDefined();
});
});
ユニットテスト(対象のコードと同じ場所に配置):
import { describe, it, expect } from "bun:test";
import { myFunction } from "./my-file";
describe("myFunction", () => {
it("returns expected value", () => {
expect(myFunction()).toBe("expected");
});
});
テストデータの分離
テストは共有ブランチに対して並列で実行されるため、各スイートがそれぞれのデータを所有する必要があります。spec ごとに一意のユーザーを生成し(例:auth-test-${uuid}@example.com)、共有リソースを避け、クリーンアップにはブランチの TTL を利用してください。他のテストのデータが存在することを決して前提にしないでください。
const testUser = await createTestUser({
email: `auth-test-${uuid}@example.com`,
});
よく使うパターン
// Protected route (Playwright)
test("redirects unauthenticated user", async ({ page }) => {
await page.goto("/protected-page");
await expect(page).toHaveURL(/sign-in/);
});
// Error state (Playwright)
test("shows error for invalid input", async ({ page }) => {
await page.goto("/form");
await page.getByRole("button", { name: /submit/i }).click();
await expect(page.getByText(/error|required/i)).toBeVisible({
timeout: 5000,
});
});
デバッグ
bunx playwright test --headed # watch the browser
bunx playwright test --debug # step through
bunx playwright show-report # HTML report
bun test --only "test name" # run a single test
bun test --watch # re-run on change
失敗した Playwright の実行ではスクリーンショットとトレースが test-results/ に保存されます。CI で失敗した場合は、ここを確認してください。