mcpField
F
frontend-testing-best-practices

frontend-testing-best-practices

github.com/sergiodxaテスト・品質922.2k 回インストール38 週間前に更新
リポジトリ

frontend-testing-best-practices について

Testing Best Practicesは、フロントエンドプロジェクトのテスト作成、レビュー、リファクタリングに役立つ指針です。コンポーネント内部ではなくユーザーから見える動作を検証し、E2Eテストを優先してモックを抑える方針です。

主な機能

  1. 01E2Eテストを優先
  2. 02単体テストは純粋関数に限定
  3. 03モックを最小限に抑制
  4. 04ユーザーに見える動作を検証
  5. 05アクセシブルなテストセレクターを使用
  6. 06E2Eテストを指定ディレクトリに配置

活用シーン

  1. 01新機能に適したテスト種別の判断
  2. 02ユーザーフローのE2Eテスト作成
  3. 03Reactのテストコードレビュー
  4. 04モックに依存するテストのリファクタリング

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/sergiodxa/agent-skills --skill frontend-testing-best-practices

インストール後、Claude Code で/frontend-testing-best-practicesを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

rules/
avoid-component-tests.md
e2e-selectors.md
e2e-test-structure.md
minimize-mocking.md
prefer-e2e-tests.md
unit-test-structure.md

詳細

テストのベストプラクティス

実際の信頼につながる、効果的で保守しやすいテストを書くためのガイドラインです。E2E テストを優先すること、モックを最小限にすること、実装ではなく振る舞いをテストすることに焦点を当てた 6 つのルールが含まれています。

基本方針

  1. ユニットテストより E2E テストを優先する - 個々の部分ではなく、システム全体をテストします
  2. モックを最小限にする - 複雑なモックが必要なら、代わりに E2E テストを書きます
  3. 実装ではなく振る舞いをテストする - ユーザーに見えるものや、ユーザーが行う操作をテストします
  4. React コンポーネントを直接テストしない - E2E を通じてテストします

適用する場面

次のような場合に、これらのガイドラインを参照してください。

  • どの種類のテストを書くかを決めるとき
  • 新しい E2E テストまたはユニットテストを書くとき
  • テストコードをレビューするとき
  • テストをリファクタリングするとき

ルールの概要

テスト戦略(重要)
prefer-e2e-tests - @rules/prefer-e2e-tests.md

基本的に E2E テストを選びます。ユニットテストを書くのは、純粋関数に限ります。

// E2E test (PREFERRED) - tests real user flow
test("user can place an order", async ({ page }) => {
  await createTestingAccount(page, { account_status: "active" });
  await page.goto("/catalog");
  await page.getByRole("heading", { name: "Example Item" }).click();
  await page.getByRole("link", { name: "Buy" }).click();
  // ... complete flow
  await expect(page.getByAltText("Thank you")).toBeVisible();
});

// Unit test - ONLY for pure functions
test("formatCurrency formats with two decimals", () => {
  expect(formatCurrency(1234.5)).toBe("$1,234.50");
});
avoid-component-tests - @rules/avoid-component-tests.md

React コンポーネントをユニットテストしないでください。E2E を通じてテストするか、テストしないでください。

// BAD: Component unit test
describe("OrderCard", () => {
  test("renders amount", () => {
    render(<OrderCard amount={100} />);
    expect(screen.getByText("$100")).toBeInTheDocument();
  });
});

// GOOD: E2E test covers the component naturally
test("order history shows orders", async ({ page }) => {
  await page.goto("/orders");
  await expect(page.getByText("$100")).toBeVisible();
});
minimize-mocking - @rules/minimize-mocking.md

モックはシンプルに保ちます。3 つ以上のモックが必要なら、代わりに E2E テストを書きます。

// BAD: Too many mocks = write E2E test
vi.mock("~/lib/auth");
vi.mock("~/lib/transactions");
vi.mock("~/hooks/useAccount");

// GOOD: Simple MSW mock for loader test
mockServer.use(
  http.get("/api/user", () => HttpResponse.json({ name: "John" })),
);
E2E テスト(高)
e2e-test-structure - @rules/e2e-test-structure.md

E2E テストは e2e/tests/ に配置します。frontend/ には配置しません。

// e2e/tests/order.spec.ts
import { test, expect } from "@playwright/test";
import { addAccountBalance, createTestingAccount } from "./utils";

test.describe("Orders", () => {
  test.beforeEach(async ({ page, context }) => {
    await createTestingAccount(page, { account_status: "active" });
    let cookies = await context.cookies();
    let account_id = cookies.find((c) => c.name === "account_id").value;
    await addAccountBalance({ account_id, amount: 10000, replaceBalance: true });
  });

  test("place order with default values", async ({ page }) => {
    await page.goto("/catalog");
    // ... user flow
  });
});
e2e-selectors - @rules/e2e-selectors.md

アクセシブルなセレクターを使用します。優先順位は、role > label > text > testid です。

// GOOD: Role-based (preferred)
await page.getByRole("button", { name: "Submit" }).click();
await page.getByRole("heading", { name: "Dashboard" });

// GOOD: Label-based
await page.getByLabel("Email").fill("[email protected]");

// OK: Test ID when no accessible selector exists
await expect(page.getByTestId("balance")).toHaveText("$1,234");

// BAD: CSS selectors
await page.locator(".btn-primary").click();
ユニットテスト(中)
unit-test-structure - @rules/unit-test-structure.md

純粋関数のみをユニットテストします。ソースファイルと同じ場所に配置します。

// app/utils/format.test.ts
import { describe, test, expect } from "vitest";
import { formatCurrency } from "./format";

describe("formatCurrency", () => {
  test("formats positive amounts", () => {
    expect(formatCurrency(1234.5)).toBe("$1,234.50");
  });

  test("handles zero", () => {
    expect(formatCurrency(0)).toBe("$0.00");
  });
});

主なファイル

  • e2e/tests/ - E2E テスト(Playwright)
  • e2e/tests/utils.ts - E2E テストユーティリティ
  • vitest.config.ts - ユニットテストの設定
  • vitest.setup.ts - MSW を使用したグローバルテストのセットアップ
  • app/utils/test-utils.ts - ユニットテストユーティリティ

コメント