| name | frontend-testing |
| description | フロントエンド(TypeScript/Svelte 5/Vitest)のテスト実装とデバッグを行います。テストの作成、テストの実行、テストエラーの修正、Svelte 5 コンポーネントのテスト、国際化対応のモックなどのテスト関連タスクに使用します。 |
| allowed-tools | Read, Edit, Write, Bash(bun run test:*), Bash(bun check:*) |
| model | sonnet |
Frontend Testing Skill
Flequit プロジェクトのフロントエンドテスト(TypeScript/Vitest/Svelte 5)を実装・実行するスキルです。
テスト実行コマンド
単一ファイルテスト(推奨)
# まず単一ファイルでテストして正確性を確認
bun run test [filename]
全テスト実行
# 単一ファイルテストが成功してから実行
bun run test
型チェック
# bun check を使用(bun run check や bun run typecheck は使用禁止)
bun check
ウォッチモード
bun run test:watch
Svelte 5 テスト対応
✅ 完全サポート: Svelte 5 の runes ($state, $props, $derived, $effect) を含むコンポーネントテストが正常に動作します。
コンポーネントテストの書き方
import { test, expect } from 'vitest';
import { render, fireEvent } from '@testing-library/svelte';
import MyComponent from '$lib/components/MyComponent.svelte';
test('Svelte 5 component test', async () => {
const { getByRole, getByText } = render(MyComponent, {
props: {
initialValue: 10
}
});
const button = getByRole('button');
await fireEvent.click(button);
expect(getByText('11')).toBeInTheDocument();
});
国際化(i18n)テストのモック
正しいアプローチ
beforeEach で setTranslationService() を使用してモックを設定:
import { test, expect, beforeEach } from 'vitest';
import { setTranslationService } from '$lib/stores/locale.svelte';
import { createUnitTestTranslationService, unitTestTranslations } from '../unit-translation-mock';
beforeEach(() => {
setTranslationService(createUnitTestTranslationService());
});
test('翻訳が必要な関数のテスト', () => {
expect(getStatusLabel('not_started')).toBe(unitTestTranslations.status_not_started);
});
重要なポイント
createUnitTestTranslationService()を使用:tests/unit-translation-mock.tsから提供される専用サービス- プロパティ参照で比較:
unitTestTranslations.some_keyを使用(文字列リテラルではなく) afterEachでの復元不要: Vitest は各ファイルを独立して実行- グローバルモック禁止:
vitest.setup.tsで翻訳関連をモックしない
避けるべきアプローチ
$paraglide/runtimeの直接モック$lib/stores/locale.svelteの完全モックvitest.setup.tsでの翻訳関連グローバルモック
これらは翻訳システムの内部実装に依存し、テストを脆弱にします。
テスト構造
ディレクトリ構造
tests/ # Unit & Integration tests
├── utils/ # ユーティリティ関数テスト
├── integration/ # インテグレーションテスト
├── **/ # ユニットテスト(src/ と同じ構造)
└── vitest.setup.ts # Vitest設定
e2e/ # E2E tests (Playwright)
├── components/ # コンポーネントテスト
└── scenario/ # シナリオテスト
テスト戦略
1. ユニットテスト
ユーティリティ関数やビジネスロジックのテスト
describe('calculateProgress', () => {
it('タスクが0個の場合は0を返す', () => {
expect(calculateProgress(0, 0)).toBe(0);
});
it('正しいパーセンテージを計算', () => {
expect(calculateProgress(3, 10)).toBe(30);
});
});
2. インテグレーションテスト
データフロー、サービス連携のテスト
test('タスク作成フロー', async () => {
const taskService = new TaskService();
const task = await taskService.createTask({
title: 'テストタスク',
projectId: 'project-1'
});
expect(task.id).toBeDefined();
expect(task.title).toBe('テストタスク');
});
3. コンポーネントテスト
Svelte コンポーネントのテスト
test('タスクアイテムコンポーネント', async () => {
const mockOnComplete = vi.fn();
const { getByRole } = render(TaskItem, {
props: {
task: { id: '1', title: 'Test', status: 'todo' },
onComplete: mockOnComplete
}
});
await fireEvent.click(getByRole('button', { name: '完了' }));
expect(mockOnComplete).toHaveBeenCalledWith('1');
});
エラーハンドリング
テスト失敗時の対応
- エラーメッセージを確認: どのアサーションが失敗したか
- 型エラーの場合:
bun checkで型チェック - 実装を確認: テスト対象のコードを読む
- 段階的にデバッグ:
console.logで中間値を確認
よくあるエラーと解決方法
1. TypeError: Cannot read properties of undefined
- 原因: モックが正しく設定されていない
- 解決: モックの戻り値を確認、必要なプロパティを追加
2. ReferenceError: document is not defined
- 原因: DOM 環境が必要
- 解決:
@testing-library/svelteを使用
3. 翻訳関連エラー
- 原因: 翻訳モックが設定されていない
- 解決:
beforeEachでsetTranslationService()を呼び出し
ベストプラクティス
1. AAA パターン(Arrange-Act-Assert)
test('example', () => {
// Arrange - テストデータとモックを準備
const data = { value: 10 };
const mockFn = vi.fn();
// Act - 対象の関数/メソッドを実行
const result = processData(data, mockFn);
// Assert - 結果を検証
expect(result).toBe(20);
expect(mockFn).toHaveBeenCalledWith(data);
});
2. テストの独立性
各テストは他のテストに依存しないこと:
// Good
describe('TaskStore', () => {
let store: TaskStore;
beforeEach(() => {
store = new TaskStore(); // 各テストで新しいインスタンス
});
test('test 1', () => { /* ... */ });
test('test 2', () => { /* ... */ });
});
// Bad - テスト間で状態が共有される
const store = new TaskStore();
test('test 1', () => { store.addTask(...); });
test('test 2', () => { /* store の状態が test 1 の影響を受ける */ });
3. 意味のあるテスト名
// Good - 何をテストしているか明確
test('空のタイトルでタスクを作成できない', () => { /* ... */ });
// Bad - 何をテストしているか不明確
test('validation', () => { /* ... */ });
関連ドキュメント
詳細は以下のドキュメントを参照:
docs/en/develop/design/testing.md- テスト戦略全体docs/en/develop/rules/testing.md- テストルールdocs/en/develop/design/frontend/svelte5-patterns.md- Svelte 5 パターン