behavioral-testing について
behavioral-testingは、簡潔で振る舞いを中心としたテストを書くためのスキルです。テストの作成者やレビュー担当者向けに、実装の詳細ではなく観測可能な結果と境界を重視し、必要に応じて参照資料も利用できます。
主な機能
- 01ユーザーに見える振る舞いをテスト
- 02準備・実行・確認の形式を使用
- 03境界条件とエラー復旧を確認
- 04外部境界のみをモック
- 05テストテンプレートとカバレッジ資料
活用シーン
- 01フォーム入力やユーザー向けエラーのテスト
- 02状態遷移とAPI障害からの復旧を検証
- 03実装詳細に依存するテストを確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ caidanw/ skills --skill behavioral-testingインストール後、Claude Code で/behavioral-testingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/anti-patterns.mdbranch-coverage.mdtest-templates.md詳細
振る舞いのテスト
観察可能な振る舞いをテストします。テストは簡潔に保ちます。実装の詳細はテストしません。
基本原則
1. Test what the user sees, not how the code works
2. If a refactor breaks a test, the test was wrong
3. Mocks isolate — they are never the thing being tested
4. Every assertion must trace to a user-observable outcome
5. Terse tests > thorough ceremony
テストの作成
パターン
Arrange: Set up the minimum preconditions
Act: Do the thing the user would do
Assert: Check what the user would see
以上です。赤・緑・赤の儀式は不要です。冗長なセットアップも不要です。テストのセットアップがアサーションより長い場合は、何かが間違っています。
テスト対象
コードのすべての行ではなく、境界での振る舞いをテストします。
| 必ずテストする | 省略する |
|---|---|
| 空/null/空白のみの入力でどうなるか | 内部メソッドの呼び出し順序 |
| ユーザーに表示されるエラーメッセージ | どのヘルパー関数が呼び出されたか |
| 状態の遷移(読み込み → 成功 → エラー) | 状態管理の実装の詳細 |
| API 障害からの復旧 | モックの呼び出し回数(それ自体が振る舞いである場合を除く) |
| ユーザーが遭遇するエッジケース | ハッピーパスのみのカバレッジ |
テストの命名
関数ではなく、振る舞いにちなんでテストに名前を付けます。
✅ "shows error when email is empty"
✅ "redirects to login after session expires"
✅ "prevents duplicate submission on double-click"
❌ "test validateEmail"
❌ "test handleSubmit calls api"
❌ "test useAuth hook returns null"
テストを簡潔に保つ
// ✅ Terse — tests one behavior, reads in 3 seconds
test('shows error when email is empty', () => {
render(<LoginForm />);
click(submitButton());
expect(screen.getByText('Email is required')).toBeVisible();
});
// ❌ Verbose — ceremony obscures intent
test('should display an error message when the user submits the form without entering an email address', () => {
const mockOnSubmit = vi.fn();
const mockOnError = vi.fn();
const { container } = render(
<LoginForm onSubmit={mockOnSubmit} onError={mockOnError} />
);
const form = container.querySelector('form');
const button = screen.getByRole('button', { name: /submit/i });
await userEvent.click(button);
expect(mockOnSubmit).not.toHaveBeenCalled();
expect(mockOnError).toHaveBeenCalledWith(expect.objectContaining({ field: 'email' }));
expect(screen.getByText('Email is required')).toBeVisible();
});
簡潔なテストでも同じバグを検出できます。冗長なテストはモックの内部状態まで検証します。振る舞いに変化がなくても、リファクタリングするとそうしたアサーションは壊れます。
確認事項
テストを作成またはレビューする前に、次の項目を確認します。
□ Am I asserting on a mock instead of real output?
→ If yes: delete the assertion or unmock it
□ Would a refactor break this test even though behavior hasn't changed?
→ If yes: the test is coupled to implementation — rewrite it
□ Is mock setup > 50% of the test?
→ If yes: use an integration test with real components instead
□ Does this test name describe a user-visible behavior?
→ If no: rename it or question whether it needs to exist
□ Did I write this test after the implementation?
→ If yes: verify it actually fails when behavior is broken, not just when code changes
モックを使う場面
外部との境界だけをモックします。 ネットワーク呼び出し、サードパーティサービス、タイマーなど、自分で制御できないものが対象です。
内部モジュール、自分たちが所有するコンポーネント、または「念のため」のモックは決して使いません。
テストするために何かをモックする必要があるなら、設計に結合の問題があります。テストではなく、設計を修正してください。
詳細なリファレンス
必要な場合にのみ、次のドキュメントを読み込みます。
- references/anti-patterns.md — テストでよくある間違いを例とともに解説します。モックの振る舞いのテスト、テスト専用の本番メソッド、不完全なモック、過剰なモックなど
- references/test-templates.md — 単体テスト、統合テスト、E2E テスト用のコピー&ペーストできるテストパターンです。ファクトリー、ヘルパー、簡潔なアサーションパターンを掲載しています
- references/branch-coverage.md — 体系的にカバレッジを確保するための分岐マトリックス手法です。条件のマッピング、優先順位付け、すべての組み合わせをテストせずに網羅性を確認する方法を解説します
コメント
Markdown 対応