本記事は、note に掲載した AITDD実践録:AIエージェント(Claude Code/Gemini CLI)だから「テストが先に動く」開発を日常化する と同じテーマ(AI 駆動開発でのテスト先行)を、Qiita 向けに「チーム開発で安定させるための観点」に角度を変えて整理したものです。
はじめに
AIコーディングエージェントを使うと、実装の初速はかなり上がります。
ただ、2025年に使っていて何度も感じたのは、実装が速いほど、仕様のズレも速く混ざるということでした。
そこで、自分はAIに実装させる前に、最低限のテスト観点を書くようにしました。
この記事では、テストコードそのものの書き方ではなく、AIに実装を依頼する前に「何を満たせばOKか」を固定する運用についてまとめます。
先に実装させて困ったこと
最初は、AIに次のように頼んでいました。
このIssueの内容を実装してください。
関連ファイルを読んで、必要な変更をしてください。
これでも動くコードは出ます。
でも、あとから確認すると、次のようなことが起きがちでした。
- エッジケースが抜ける
- 期待する失敗時の挙動が曖昧になる
- 実装後にテストを合わせにいってしまう
- レビュー時に「何を満たせばOKか」を再確認する
AIが悪いというより、入力が実装寄りすぎたのだと思います。
特に困ったのは、「動いているように見えるけれど、期待していた仕様とは少し違う」変更でした。
たとえば、保存ボタンの制御を直してほしいだけだったのに、AIが入力中のエラー表示や送信後の通知まで調整することがあります。
単体では便利そうでも、チーム開発では確認対象が増えます。
このとき、先にテスト観点がないと、レビュー中に「そもそも今回の正解は何だったか」を話し合うことになります。
テスト観点を先に書く
そこで、実装前に次のような短いメモを置くようにしました。
この記事では、特定のフレームワークやテストランナーの設定には踏み込みません。そこを詳しく書くと技術ガイドになりますが、ここで残したいのは、チームでAIを使うときに「何を先に固定すると迷いにくいか」です。
# test-cases.md
## 正常系
- 入力Aのとき、結果Bになる
## 異常系
- 必須値がないとき、エラー表示になる
## 境界値
- 空文字のとき、保存処理を走らせない
## 回帰確認
- 既存の表示や保存処理は変えない
ポイントは、最初から完全なテストコードにしないことです。
まずは、人間が期待する振る舞いを固定します。
たとえば、保存ボタンの修正なら、このくらい具体的に書きます。
# test-cases.md
## 正常系
- 必須項目をすべて入力すると、保存ボタンを押せる
- 保存に成功したら、保存済みの表示になる
## 異常系
- 必須項目が空のとき、保存ボタンを押せない
- APIが500を返したとき、保存済み表示にしない
- APIが500を返したとき、再試行できるエラー文言を表示する
## 境界値
- 入力が空白だけのとき、未入力として扱う
## 回帰確認
- 既存の入力値は保存失敗後も消えない
- 既存の成功時メッセージの文言は変えない
ここで大事なのは、網羅性よりも判断可能性です。
レビューする人が「この項目は満たしている」「これは満たしていない」と判断できる粒度で書きます。
AIへの依頼文も変える
テスト観点を書いたあとは、AIへの依頼も変えます。
まず test-cases.md を読み、今回満たすべき振る舞いを要約してください。
その後、実装計画を作ってください。
まだコードは変更しないでください。
いきなり実装させないのがポイントです。
AIがテスト観点をどう理解したかを先に見ると、仕様のズレを早い段階で見つけやすくなります。
この時点で、AIの要約がずれていたら実装前に直します。
理解が少し違います。
今回は「保存失敗時に入力値を残す」ことが重要です。
通知文言の全面見直しはしないでください。
この前提で実装計画を作り直してください。
実装後にこの修正をすると、差分を戻したり、テストを直したりする必要があります。
実装前なら、会話を数行足すだけで済みます。
実装後の確認も楽になる
実装後は、AIに次の形で確認させます。
test-cases.md の各項目について、どの変更で満たしたかを説明してください。
満たせていない項目があれば、未対応として明記してください。
この出力があると、人間のレビューも始めやすくなります。
レビューの入口が「コード全体を読む」ではなく、「事前に決めたテスト観点と差分が対応しているか」になるからです。
このとき、できればチェック表として出させます。
| 観点 | 対応 | 確認方法 |
| --- | --- | --- |
| 必須項目をすべて入力すると保存ボタンを押せる | 対応済み | Unit test / 手動確認 |
| APIが500を返したとき保存済み表示にしない | 対応済み | Unit test |
| 既存の成功時メッセージの文言は変えない | 未確認 | 目視確認が必要 |
完璧な表である必要はありません。
人間がレビューで見る順番を作ることが目的です。
よかったこと
このやり方でよかったのは、AIの自由度を下げすぎずに、確認の軸を固定できることでした。
AIには実装の探索を任せます。
一方で、何を満たすべきかは先に人間が決めます。
この分担にすると、AIの出力を後から追いかける時間が減りました。
特にチーム開発では、次の効果がありました。
- レビューで見る観点が揃う
- スコープ外の改善に気づきやすい
- 「動いたからOK」になりにくい
- 途中でセッションが切れても再開しやすい
- 実装者以外も、PRの意図を追いやすい
最後の点は、地味ですがかなり効きます。
AIとのやり取りは、実装した本人の手元に閉じがちです。
テスト観点を先に残しておくと、あとから参加した人も「何を満たすための変更か」を読み取れます。
注意点
テスト観点を書いたからといって、AIの出力が必ず正しくなるわけではありません。
むしろ、テスト観点はAIを信用するためではなく、人間が判断しやすくするための道具です。
曖昧な観点を書けば、曖昧な実装になります。
だから、最初は少なくてもいいので、具体的に書く方が効きます。
NG: エラー処理をちゃんとする
OK: APIが500を返したとき、保存済み表示を出さず、再試行できるエラー文言を表示する
もう一つの注意点は、テスト観点を実装に合わせて後から書き換えないことです。
実装してみた結果、観点のほうが間違っていたと分かることはあります。その場合は、観点を直してよいと思います。
ただし、「AIがこう実装したから、この観点は満たしたことにする」と寄せてしまうと、先に書いた意味が薄れます。
変更するなら、PR上で次のように理由を残すほうがよいです。
実装前は「保存失敗時に入力値をすべて残す」としていたが、
セキュリティ上、トークン項目はクリアする必要があるため観点を変更した。
テスト観点も仕様の一部として扱うと、レビューで合意しやすくなります。
まとめ
2025年にAIコーディングエージェントを使ってみて、実装前のテスト観点がかなり重要だと感じました。
AIはコードを書くのが速いです。
だからこそ、何を満たすべきかを先に固定しないと、あとから人間が仕様を追い直すことになります。
実装の前に、テスト観点を書く。
AIにまず理解を要約させる。
実装後に、差分とテスト観点の対応を説明させる。
この小さな順番の変更だけで、AIとのチーム開発はかなり扱いやすくなりました。