frontend-testing について
Vitestと@testing-library/svelteを使うチーム向けのフロントエンドテストガイドです。テスト配置、TDDとAAAの実践、アクセシブルなクエリの優先順位、モジュールのモック例を示します。
主な機能
- 01VitestとTesting Libraryの構成
- 02テストファイルの配置規約
- 03TDDとArrange-Act-Assertのパターン
- 04アクセシブルなクエリの選択順
- 05モジュールモックの例
活用シーン
- 01Svelteコンポーネントのテスト作成
- 02バグ修正時のテスト追加
- 03アクセシブルなテストクエリの選択
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ exceptionless/ exceptionless --skill frontend-testingインストール後、Claude Code で/frontend-testingを入力して読み込まれたか確認します。
詳細
フロントエンドのテスト
ドキュメント: vitest.dev | testing-library.com
フレームワークと配置場所
- フレームワーク:Vitest + @testing-library/svelte
- 配置場所:コードと同じ場所に
.test.tsまたは.spec.tsとして配置します - TDD ワークフロー:バグ修正や機能追加の際は、まず失敗するテストを書きます
AAA パターン
Arrange、Act、Assert の領域を明示します。
import { describe, expect, it } from "vitest";
describe("Calculator", () => {
it("should add two numbers correctly", () => {
// Arrange
const a = 5;
const b = 3;
// Act
const result = add(a, b);
// Assert
expect(result).toBe(8);
});
});
スパイを使ったテスト
import { beforeEach, describe, expect, it, vi } from "vitest";
import { CachedPersistedState } from "./cached-persisted-state.svelte";
describe("CachedPersistedState", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("should return cached value without reading storage repeatedly", () => {
// Arrange
const getItemSpy = vi.spyOn(Storage.prototype, "getItem");
localStorage.setItem("test-key", "value1");
const state = new CachedPersistedState("test-key", "default");
getItemSpy.mockClear();
// Act
const val1 = state.current;
const val2 = state.current;
// Assert
expect(val1).toBe("value1");
expect(val2).toBe("value1");
expect(getItemSpy).not.toHaveBeenCalled();
});
});
クエリ選択の優先順位
実装の詳細ではなく、アクセシブルなクエリを使用します。
screen.getByRole("button", { name: /submit/i })— ロールベース(推奨)screen.getByLabelText("Email address")— ラベルベースscreen.getByText("Welcome back")— テキストベースscreen.getByTestId("complex-chart")— テスト ID(代替手段)- ❌
screen.getByClassName("btn-primary")— 実装の詳細は使用しないでください
モジュールのモック
import { vi, describe, it, beforeEach, expect } from "vitest";
import { render, screen } from "@testing-library/svelte";
vi.mock("$lib/api/organizations", () => ({
getOrganizations: vi.fn(),
}));
import { getOrganizations } from "$lib/api/organizations";
import OrganizationList from "./organization-list.svelte";
describe("OrganizationList", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("displays organizations from API", async () => {
// Arrange
vi.mocked(getOrganizations).mockResolvedValue([{ id: "1", name: "Org One" }]);
// Act
render(OrganizationList);
// Assert
expect(await screen.findByText("Org One")).toBeInTheDocument();
});
});
コメント
Markdown 対応