はじめに
AI に「テストを書いて」と頼むと、正常系だけのテストが返ってくることがあります。
もちろん正常系は必要です。ただ、バグを減らす目的でテストを書いているのに、invalid input、認可、重複実行、エラー時の表示が抜けると、後で人間が観点を足し直すことになります。
この記事では、AI にテスト実装を頼む前に、観点リストを先に渡す運用をまとめます。
TL;DR / 結論コード
テスト依頼の前に、次の表を埋めます。
テスト観点:
- 正常系: 代表的な入力で期待結果になる
- 境界値: 0件、1件、上限件数、空文字、null
- 不正入力: 型不一致、必須欠落、範囲外
- 認可: 未ログイン、他ユーザー所有データ、権限不足
- エラー: 外部API失敗、DB失敗、タイムアウト
- 冪等性: 同じ操作を2回実行しても重複しない
- 回帰: 既存の主要導線が壊れない
そのうえで、今回の対象に不要な観点は 該当なし と明記します。
何に詰まったか
AI に「この機能のテストを追加して」と頼むと、次のようなテストになりがちでした。
test("saves settings", async () => {
await saveSettings({ theme: "dark" });
expect(await loadSettings()).toEqual({ theme: "dark" });
});
これは必要なテストですが、これだけでは次のケースが見えません。
- 空の設定を渡したらどうなるか
- 壊れた JSON を読んだらどうなるか
- 同じ保存を2回実行したら重複しないか
- 読み込みに失敗したときにユーザーへ何を返すか
- 既存設定との互換性は保たれるか
人間が後から「このケースも」と足していくと、テストの意図が散らばります。
原因
原因は、依頼文が「テストを書く」という作業名だけだったことです。
AI は手元のコードから代表的な happy path を見つけるのは得意です。一方で、仕様として明文化されていない境界値や認可条件は、依頼文に出てこないと優先度が下がります。
そこで、実装前にテスト観点を渡すようにしました。
観点リストの使い方
1. まず観点を列挙する
最初に広めの観点を渡します。
今回のテストで見たい観点:
- 正常系
- 空データ
- 上限件数
- 入力不正
- 未ログイン
- 他ユーザーのデータ
- 外部API失敗
- 重複実行
- 既存データ互換
この時点では、まだテスト名を書かせません。先に「どの観点が必要か」を整理させます。
2. 該当なしも明示する
不要な観点は消すのではなく、該当なし と書きます。
認可: 該当なし。ローカルのみの設定保存でユーザー所有データを扱わない。
外部API失敗: 該当なし。対象処理はネットワークに出ない。
冪等性: 同じ設定保存を2回実行しても1件として扱う。
これにより、レビュー時に「見落としたのか、意図的に外したのか」が分かります。
3. テスト名に期待結果まで入れる
テスト名は「何をしたらどうなるか」まで書かせます。
test("returns default settings when stored JSON is broken", async () => {
await writeRawSettings("{broken");
const settings = await loadSettings();
expect(settings).toEqual(defaultSettings);
});
handles error だけだと、何を期待しているかが読めません。テスト名に結果まで入れると、実装を変えたときのレビューが楽になります。
注意点
観点リストを渡しても、すべてを自動でテストにする必要はありません。
外部API、DB、ブラウザ、時間依存の処理は、無理に重い統合テストへ寄せると保守コストが上がります。単体テストで見る範囲、統合テストで見る範囲、手動確認に残す範囲を分けます。
また、AI が生成したテストは、同じAIに自己採点させるだけでは不十分です。少なくとも失敗時のメッセージ、テスト名、fixture の現実性は人間か別エージェントで見直します。
まとめ
AI にテストを書かせる前に観点リストを渡すと、正常系だけに寄る問題を減らせました。
- 作業名ではなく、見たい観点を先に渡す
- 不要な観点は
該当なしと明記する - テスト名に期待結果まで入れる
- 重いテストに寄せすぎず、確認範囲を分ける
「テストを書いて」ではなく「この観点を満たすテストを書いて」と渡す方が、レビュー可能な成果物になりました。
参考リンク
- harness17/zenn-articles - 本記事で扱った記事リポジトリ
- AIに実装を任せる前に完成条件を宣言するSprint Contract運用 - 完成条件としてテスト観点を先に置く関連運用
- AIに「修正して」と頼むと無関係コードまで触られる問題をSurgical Changesルールで抑えた - AI への事前制約の関連運用