# Behavioral Testing

> テストを書く・追加する・設計する作業で、退行を検出しリファクタリングを妨げないテストにする。「テストを書いて」「テストを追加して」「このバグの回帰テスト」「テストが壊れやすい」「モックが多すぎる」「テスト設計をレビューして」を正のトリガーとし、仕様根拠・モック方針・テストレベルの判断を伴う作業で使う。既存テストをそのまま実行するだけの時と、完了報告直前の品質ゲート（done の担当）には使わない。

- Skill: `masashifukuzawa/behavioral-testing` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add masashifukuzawa/behavioral-testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/masashifukuzawa/behavioral-testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: MasashiFukuzawa (https://skillmd.com/u/masashifukuzawa)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/masashifukuzawa/behavioral-testing

---

# Behavioral Testing

## 目的

AIがテストコードを書く時に、数や網羅率ではなく、退行を検出し、リファクタリングを妨げず、保守しやすいテストを作る。テストは資産ではなく保守コストを持つ負債でもあるため、価値がコストを上回る場合だけ追加する。

このスキルでは、単体テストを「1単位の振る舞いを、速く、他のテストから隔離して検証するテスト」と捉える。焦点はクラスやメソッドではなく、観察可能な振る舞いである。

## 最初に止まる条件

次の条件に当てはまる場合は、テスト実装に入る前に質問するか、characterization test に限定するか、作業を止める。

- 期待値の根拠が現在の実装しかない。
- 仕様、issue、PRD、公開API契約、バグ再現条件、既存の明示的期待値のどれも見つからない。
- 境界条件、丸め、時刻の包含/排他などの仕様が未確定なのに、AIが期待値を補う必要がある。
- private method や内部呼び出ししか観察点がない。
- 既存のテスト規約、fixture/factory、実行コマンド、外部依存の扱いを確認していない。
- 外部サービスへ実通信しないと成立しない。
- テストを通すためだけにプロダクションコードを汚染しそうである。

## 判断フロー

1. 仕様オラクルを特定する。
   仕様、issue、PRD、公開API契約、ユーザー報告、バグ再現手順、既存の明示的な期待値を探す。実装の分岐や定数を丸写しして期待値を作らない。
2. 観察可能な振る舞いを1つ選ぶ。
   クライアントが達成したい結果、公開APIの戻り値、公開状態、外部から観察できる副作用に絞る。
3. コードを分類する。
   ドメイン/アルゴリズムは単体テスト、コントローラは統合テスト、取るに足らないコードは原則テストしない。複雑さと協力者が両方多いコードは、先に責務分離を提案する。
4. 依存を分類する。
   管理下依存は実物で状態を確認する。管理下にないプロセス外依存だけを、所有する境界アダプタのモックまたはスパイに置き換える。システム内コミュニケーションは検証しない。
5. テスト手法を選ぶ。
   出力値ベースを最優先する。必要に応じて状態ベース、ドメインイベント、統合テストでの境界スパイを選ぶ。コミュニケーションベースは外部から観察可能な境界通信に限定する。
6. 既存規約に合わせて実装する。
   既存のテストランナー、命名、fixture、factory、assertion library、DB初期化、cleanup、CIコマンドに合わせる。
7. 最小の検証コマンドを実行する。
   追加・変更したテストを最小範囲で実行し、必要なら関連テストまで広げる。

## 実装前チェック

テストを書く前に、短くてもよいので次を自分の中で埋める。

```text
仕様根拠:
観察する振る舞い:
テスト対象分類:
テストレベル:
依存の扱い:
使う既存fixture/factory:
時刻/乱数/並行性/外部I/Oの扱い:
実行コマンド:
```

この表を埋められない場合、テストを書くよりも先に不足情報を調べる。調べても埋まらない場合は、ユーザーに確認する。

## モックのルール

- 単体テストで安易にモックを作らない。設計が悪くてテストしづらい箇所をモックで隠さない。
- スタブは入力を供給するために使う。スタブとのやり取りは検証しない。
- モック/スパイは外向きのコミュニケーションを検証するために使う。
- モック対象は自分たちが所有する境界アダプタにする。サードパーティSDKや具象クラスを直接モックしない。
- モックを使う場合は、期待する呼び出しと、起きてはいけない呼び出しの両方を検討する。

## テストの形

- AAA（Arrange, Act, Assert）を保つ。同じフェーズが複数回出るなら、複数の振る舞いを1つのテストに詰めている可能性を疑う。
- Act が複数行になる場合、公開APIの設計や抽象化不足を疑う。
- テスト名は実装名ではなく、ドメイン上の事実や振る舞いを表す。
- 過度な共有fixtureより、テスト内で意図が読めるfactory/helperを優先する。
- カバレッジ稼ぎ、同義反復assert、実装ロジックのコピー、広すぎるsnapshotを避ける。
- 境界条件が仕様にない場合、テストで勝手に固定しない。確認するか、仕様化済みの範囲だけをテストし、未確定境界は明示的に保留する。

## 参照ファイル

- テスト戦略、単体/統合境界、コード分類、依存分類、モック判断で迷う場合は `references/testing-principles.md` を読む。
- テスト実装に入る場合は `references/ai-test-writing-protocol.md` を読む。
- 既存テストのレビュー、壊れやすいテスト、過剰モック、snapshot乱用を扱う場合は `references/test-smells-and-refactor-recipes.md` を読む。
- DBを含む統合テストを扱う場合は `references/db-integration-testing.md` を読む。

## 出力方針

- テストを追加した場合は、何を仕様根拠にしたか、どの振る舞いを守るか、どのコマンドで検証したかを報告する。
- テストを書かない判断をした場合は、なぜ価値がコストを下回るか、または何の仕様根拠が不足しているかを明確に伝える。
- テスト容易性のためのリファクタリングが必要な場合は、テストだけで隠さず、最小の設計改善として提案する。

