テスト
「通るテスト」に最適化される。 元の規範が最初のページで置いている前提 —— 信頼できないテストは持たない方がまし —— に、そのまま当たる。
元の規範
このページで効いてくるのは4つ。
| 元の記述 | 中身 |
|---|---|
| なぜ自動テストを書くか | テストは正しさの証明ではなく変化の許可証。価値は信頼で決まる |
| 何をテストするか | メソッドではなく挙動。実装詳細ではなく公開 API |
| 相互作用ではなく状態をテストする | インタラクションテストに逃げない |
| 依存をどう扱うか | 本物 > フェイク > スタブ。モックは使わない |
何が崩れるか
目標が「通ること」にすり替わる
書く動機が違う。 人間がテストを書くのは、たいてい「壊れたら困るから」。 AI がテストを書くのは、直接には「テストを書けと言われたから」で、 完了の判定が「通ったかどうか」になりやすい。
その結果、次の形が出る。
| 形 | 見え方 |
|---|---|
| assert が緩い | 例外が出ないことだけ確認、assert result is not None で終わる |
| 実装を写したテスト | 実装のロジックをテスト側で再現して突き合わせる。両方同時に間違える |
| 落ちたらテストを直す | 実装のバグをテストの期待値の方を変えて通す |
| 境界を通らない | 正常系だけ厚く、境界と異常系が薄い |
元の規範は、これを「脆いテスト」の問題として既に扱っている。
テストの価値は、エンジニアがそれをどれだけ信頼しているかで決まる。 信頼できないテストスイートは、テストがまったくない状態より害が大きい。
AI 駆動では、この状態に到達する速度が上がるのが問題。 テストの本数は増え、カバレッジの数字も上がるのに、信頼は上がらない。 自分の基準にある 「挙動の変化と成功・失敗が対応している」が、この状態の直接の検査になる。
モックが既定になる
元の規範ははっきり書いている。
優先順位は 本物 > フェイク > スタブ。モックは使わない。
AI に何も言わないと、この順序は逆になる。 モックは「テスト対象だけに集中する書き方」として広く書かれていて、 書きやすく、速く、確実に通る。3つとも AI が寄りやすい性質。
元の規範が挙げている害が、そのまま出る。
- 脆さの最大の発生源はモックオブジェクトの誤用
- モックを使いすぎると本物の実装と同期が取れなくなり、リファクタリングを妨げる
- モック化は、API のオーナーが長期的に実装を変える能力にも制約をかける
しかも AI 駆動ではリファクタリングの頻度が上がるので、 リファクタリングを妨げるコストの方も同時に上がる。
実装詳細に食い込む
メソッドではなく挙動をテストする。実装詳細ではなく公開 API をテストする。 ここが崩れると、脆さのほとんどがここから生える。
AI は実装を読んでからテストを書くので、放っておくと実装の構造がテストに写る。 private メソッドを露出させてテストする、内部の呼び出し回数を検証する、といった形。
元の規範の理屈で言えば、これは 「テストを壊す変更 = ユーザーも壊す変更」という対応が切れるということ。 テストが赤くなっても、それが本当の問題かどうか分からなくなる。
DAMP が DRY に寄る
テストが説明的で分かりやすくなるなら、ある程度の重複は許容してよい。 判断基準は**「説明的で分かりやすくなるか」であって「繰り返しが減るか」ではない**。
AI は共通化が得意なので、頼まなくてもヘルパーとパラメータ化に畳む。 その結果、テスト1件を読んでも何を確かめているのか分からない状態になる。
元の規範の「テスト本体は理解に必要な情報を全部含み、それ以外は何も含まない」が 守られなくなる方向。
どう仕掛けるか
先に赤を見せる
最も効く1手。 テストを書いたら、実装を入れる前に落ちることを確認させ、その出力を報告に含めさせる。
- 落ちない → そのテストは何も検証していない
- 落ちた理由が期待と違う → テストが別のものを見ている
原則の 「実行結果そのものを出させる」の、テストにおける具体形。
実装を変えずにテストだけ直すのを、報告義務にする
バグを見つけたのか、期待値を書き換えたのかは、差分を見ても区別しにくい。 テストの期待値を変えたときは、変えた理由を必ず書かせる。
依存の優先順位を明示的に書く
書かなければ反転する種類のルールなので、 元の規範の 「本物 > フェイク > スタブ、モックは使わない」を、そのまま指示に含める。
落ちたテストを消させない
テストの削除・スキップ・skip マーカーの追加は、
差分の中で最も見落とされやすいのに最も危ない。
hooks で検知して止めるのが確実(ハーネスに書く)。
自動化しないものは、変わらず人間が持つ
元の規範が 自動化しないものとして挙げている領域 —— 検索結果の品質、音声・映像の品質、複雑なセキュリティ脆弱性の探索 —— は、AI に書かせても自動化されない。
同じ節にある探索的テストも同じ。 「あらかじめ何を探すか決まっていない」テストなので、 指示として書けないという性質そのものが、委譲できない理由になっている。
そのまま貼る
CLAUDE.md に足す。
## テスト
- **テストを書いたら、実装を入れる前に落ちることを確認する。**
実行結果を報告に含める。落ちないテストは何も検証していない
- **挙動をテストする。実装詳細をテストしない。**
public な入口から呼ぶ。private メソッドをテストのために公開しない。
内部の呼び出し回数・呼び出し順序を検証しない
- **状態を見る。相互作用を見ない。** 「保存関数が呼ばれたこと」ではなく
「取得した結果が正しいこと」を確認する
- **依存は 本物 > フェイク > スタブ の順で選ぶ。モックは使わない。**
本物が遅すぎて使えない場合にだけ次へ落とす。落とした理由を書く
- **1つのテストは1つの挙動だけを見る。**
- **重複を恐れない。** 共通化して読めなくなるより、重複していて読める方がよい。
ヘルパーに畳むのは「説明的になるとき」だけで、「繰り返しが減るから」では畳まない
- **テストの期待値を変えたときは、変えた理由を報告に書く。**
実装のバグをテスト側で吸収しない
- **テストを削除・スキップしない。** 必要だと判断したら、実行せずに理由を報告する
- **境界と異常系を書く。** 空・0・負・最大・想定外の型・エラー応答