principle-test-behavior-not-implementation について
内部構造ではなく、観察可能な振る舞いを基準にテストを評価するスキルです。契約違反を検出し、リファクタリング後も維持しやすいテストの作成を支援します。
主な機能
- 01振る舞いと実装の区別
- 02二種類のコード変更によるテスト評価
- 03具体的な入力と期待結果の利用
- 04契約に基づくアサーション
- 05観察可能な不変条件への対応
活用シーン
- 01既存テストスイートのレビュー
- 02公開インターフェースのテスト作成
- 03リファクタリングに弱いテストの削減
- 04要件に照らしたアサーションの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ericlitman/ open-pstack --skill principle-test-behavior-not-implementationインストール後、Claude Code で/principle-test-behavior-not-implementationを入力して読み込まれたか確認します。
詳細
実装ではなく振る舞いをテストする
テストとは、コードが利用者(呼び出し元、エンドユーザー、別のサービス)に対して何をするかについての主張です。振る舞いとは、利用者が使用するインターフェースを通じて観察できることです。これには、戻り値、エラー、読み戻せる状態、コードの外部にあるシステムへの作用(リクエストの送信、行の書き込み、メッセージの発行など)が含まれます。実装とは、利用者が観察できないものです。プライベートなヘルパー、内部の呼び出し順序、中間データ、どの内部の協調コンポーネントが処理を担当したか、などが該当します。
次の2つの変更を想定し、それぞれのテストを評価してください。
- 振る舞いを壊す。 コードが誤った値を返す、作用を省略する、または作用を二重に実行するように変更します。それでもテストが通るなら、そのテストは何も証明していません。よくある原因は、契約より緩いアサーション、テスト対象のコードが算出した期待値、値を読み取るコードを実行せずに定数やプロンプト文字列を書き直しただけのテスト、そしてテスト自身が作成したデータに対するアサーションです。
- 内部を変更する。 観察可能な結果はすべて同じまま、コードの内部構造を変更します。そのときテストが失敗するなら、テストは実装に過度に依存しています。リファクタリングのたびに書き直す必要がある一方で、バグは検出できません。
最初の変更を検出し、2つ目の変更には耐えるテストは残してください。それ以外は書き直すか削除してください。両方を満たすテストを書くには、具体的な入力を用いて、利用者が使うインターフェースからコードを動かします。期待値はコードの実行結果ではなく、要件から導き出してください。契約が約束する内容を、過不足なくアサートしてください。
判断基準はアサーションの形ではなく、契約です。「空のカートには決して課金しない」という約束がある場合、決済クライアントが呼び出されなかったというアサーションは振る舞いを検証しています。テストで呼び出しを検出できることを示すため、課金が発生するケースも組み合わせてください。モックした外部サービスが受け取るペイロードは、そのサービスが観察するものなので振る舞いです。内部ヘルパーの呼び出しは、利用者には見えないため実装です。該当するレコードがない場合、空のリストが厳密な答えになることもあれば、テストで何らかの結果さえ得られればよいときには、形だけのチェックにもなります。呼び出し元が参照しない正確なエラーメッセージをアサートすると、文言に過度に依存します。呼び出し元が分岐に使うエラーの型こそが契約です。
呼び出しではなく、2つのテーブルに存在しなければならないキーや、コンパイル時の型チェックなどの不変条件をテストで固定することもできます。その不変条件が振る舞いです。