AgentSkillsCN

test

测试编写技能。在新功能上线后或完成 Bug 修复后自动启动,为 Vitest + Testing Library 测试框架提供全面支持,助力打造高效、可靠的测试用例。

SKILL.md
--- frontmatter
name: test
description: テスト作成スキル。新機能実装後、バグ修正後に自動発動。Vitest + Testing Libraryでのテストパターンを支援。

テスト作成スキル

Dayoptのテスト作成を支援するスキル。Vitest + Testing Libraryを使用。

When to Use(自動発動条件)

以下の状況で自動発動:

  • 新機能の実装が完了した時
  • バグを修正した時
  • 「テスト」「test」「テストを書いて」キーワード

技術スタック

ツール用途
Vitestテストランナー
Testing Libraryコンポーネントテスト
MSWAPIモック(必要に応じて)

テスト配置ルール

code
src/features/{feature}/
├── components/
│   ├── MyComponent.tsx
│   └── __tests__/
│       └── MyComponent.test.tsx
├── hooks/
│   ├── useMyHook.ts
│   └── __tests__/
│       └── useMyHook.test.ts
└── utils/
    ├── myUtil.ts
    └── __tests__/
        └── myUtil.test.ts

テスト実行コマンド

bash
# 単一ファイル
npm run test -- path/to/file.test.ts

# 特定のディレクトリ
npm run test -- src/features/calendar/

# 全体
npm run test

# ウォッチモード
npm run test -- --watch

テストパターン

ユニットテスト(関数)

typescript
import { describe, it, expect } from 'vitest';
import { formatDate } from '../formatDate';

describe('formatDate', () => {
  it('正常系: 日付をフォーマットする', () => {
    const date = new Date('2024-01-15');
    expect(formatDate(date)).toBe('2024/01/15');
  });

  it('エッジケース: 無効な日付', () => {
    expect(() => formatDate(null as any)).toThrow();
  });
});

コンポーネントテスト

typescript
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi } from 'vitest';
import { Button } from '../Button';

describe('Button', () => {
  it('renders correctly', () => {
    render(<Button>Click me</Button>);
    expect(screen.getByRole('button')).toHaveTextContent('Click me');
  });

  it('calls onClick when clicked', async () => {
    const handleClick = vi.fn();
    render(<Button onClick={handleClick}>Click</Button>);

    await userEvent.click(screen.getByRole('button'));
    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  it('is disabled when disabled prop is true', () => {
    render(<Button disabled>Disabled</Button>);
    expect(screen.getByRole('button')).toBeDisabled();
  });
});

フックテスト

typescript
import { renderHook, act } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import { useCounter } from '../useCounter';

describe('useCounter', () => {
  it('初期値が設定される', () => {
    const { result } = renderHook(() => useCounter(10));
    expect(result.current.count).toBe(10);
  });

  it('incrementで値が増える', () => {
    const { result } = renderHook(() => useCounter(0));

    act(() => {
      result.current.increment();
    });

    expect(result.current.count).toBe(1);
  });
});

Zustand storeテスト

typescript
import { describe, it, expect, beforeEach } from 'vitest';
import { useMyStore } from '../myStore';

describe('myStore', () => {
  beforeEach(() => {
    // ストアをリセット
    useMyStore.setState({ count: 0 });
  });

  it('初期状態', () => {
    const state = useMyStore.getState();
    expect(state.count).toBe(0);
  });

  it('increment action', () => {
    useMyStore.getState().increment();
    expect(useMyStore.getState().count).toBe(1);
  });
});

テストケース設計

3つのカテゴリ

カテゴリ内容優先度
正常系期待通りの入力必須
エラー系異常な入力、エラーハンドリング必須
エッジケース境界値、空配列、null推奨

テストケース例

typescript
describe('calculateTotal', () => {
  // 正常系
  it('正の数の合計を計算する', () => { ... });

  // エラー系
  it('空配列でエラーを投げる', () => { ... });

  // エッジケース
  it('1要素の配列', () => { ... });
  it('負の数を含む配列', () => { ... });
  it('小数を含む配列', () => { ... });
});

Dayopt固有のパターン

tRPCエンドポイントのテスト

typescript
// サービス層を直接テスト
import { createTagService } from '../services/tag';

describe('TagService', () => {
  it('タグを作成する', async () => {
    const mockSupabase = createMockSupabase();
    const service = createTagService(mockSupabase);

    const result = await service.create({
      userId: 'user-1',
      name: 'Test Tag',
    });

    expect(result.name).toBe('Test Tag');
  });
});

カレンダーコンポーネントのテスト

typescript
// ドラッグ操作のテストは複雑なため、
// ユニットテストは状態管理に集中
describe('useCalendarDrag', () => {
  it('ドラッグ開始で状態が更新される', () => { ... });
  it('ドラッグ終了で状態がリセットされる', () => { ... });
});

出力形式

markdown
## テスト作成完了

### 作成したテスト

| ファイル                       | テスト数 | 内容             |
| ------------------------------ | -------- | ---------------- |
| `__tests__/formatDate.test.ts` | 3        | 日付フォーマット |

### カバレッジ

- 正常系: 2件
- エラー系: 1件
- エッジケース: 0件

### 実行結果

✓ formatDate > 正常系: 日付をフォーマットする ✓ formatDate > 正常系: 時刻を含む日付 ✓ formatDate > エラー系: 無効な日付

code

チェックリスト

テスト作成時:

  • 正常系をカバーしたか
  • エラー系をカバーしたか
  • テストが独立しているか(他のテストに依存しない)

テスト実行時:

  • npm run test が通るか
  • 新しいテストが既存テストを壊していないか

関連スキル

  • /debug - テスト失敗時のデバッグ
  • /refactor - テスト追加後のリファクタリング