「テストは AI に書かせれば速い」。確かにそのとおりで、生成 AI を使えばテストコードの作成量は一気に増えます。ただ実プロジェクトに組み込んでみると、本数は増えたのにバグは減らない、カバレッジは高いのに本番で落ちる、という状況にぶつかることが珍しくありません。テストの自動生成は「量を増やす技術」であって、「品質を保証する技術」ではないからです。

本記事では、生成 AI にテストを書かせるときの前提と原則から、ユニット・結合・E2E のレイヤー別アプローチ、テストファーストと AI を組み合わせる具体手順、AI が書くテスト特有の落とし穴、カバレッジとレビューの考え方、CI への組み込み、そして FIXIT の品質ゲート構成例までを、実装目線で掘り下げます。テストを AI に書かせて品質まで引き上げたい、というエンジニアに向けた実践ガイドです。

AI にテストを書かせる前提と原則

最初に押さえておきたいのは、AI はテストを書くのが得意だが、「何を保証すべきか」を決めるのは苦手だという事実です。

テストコードは、突き詰めれば「仕様を実行可能な形で固定したもの」です。仕様が曖昧なまま「このコードのテストを書いて」と頼むと、AI は目の前の実装をなぞるテストを生成します。実装が間違っていても、その間違いごとテストに固定してしまう。これがテスト自動生成の最大の罠です。テストが実装の鏡になり、バグを検出する力を失います。

そこで原則になるのが次の考え方です。

  • 仕様 (何が正しいか) は人間が決める。テストケースの列挙とコード化は AI に任せる
  • テストは「実装をなぞる」のではなく「仕様を検証する」ものとして書かせる
  • 生成されたテストは、わざとバグを入れたら落ちるかという観点でレビューする
  • 境界値・異常系・並行性といった人間が見落としやすい領域こそ AI に列挙させる

AI に投げる前に、入力と期待される出力の例、境界条件、起こしてはいけない副作用を言語化しておくと、生成されるテストの質が大きく変わります。仕様を渡さずに量だけ増やしても、通って当然のテストが積み上がるだけで、品質ゲートとしては機能しません。AI 駆動開発全体の品質設計については AI 駆動開発の品質保証 で体系的に扱っているので、本記事はその中でもテスト自動化の実装に絞って解説します。

ユニット / 結合 / E2E のレイヤー別アプローチ

テストは一枚岩ではありません。レイヤーごとに、AI に任せやすい度合いも、書かせ方も変わります。いわゆるテストピラミッド (ユニットを厚く、E2E を薄く) の考え方は、AI を使う場合でも基本は変わりません。むしろ AI は下層のユニットテストを量産するのが得意なので、ピラミッドの形を保ちやすくなります。

ユニットテスト

最も AI と相性が良いレイヤーです。関数やクラス単位で、入力に対する出力を検証するため、依存が少なく、ケースの列挙が機械的に効きます。純粋関数や変換ロジック、バリデーション、計算系はとくに任せやすい領域です。

書かせ方のコツは、対象の関数のシグネチャと仕様を渡したうえで「正常系・境界値・異常系をそれぞれ列挙してからテストにして」と段階を分けることです。いきなりコードを出させるより、まずケースの一覧を出させてレビューし、抜けや過剰を直してからコード化したほうが、結果的に早く、質も安定します。

結合テスト

複数モジュールやデータベース、外部サービスをまたぐレイヤーです。ここからは「何をモックして、何を本物で通すか」という設計判断が入るため、AI に丸投げしにくくなります。AI は気軽に外部 API を本物で叩くテストや、固定値に強く依存した壊れやすいテストを書きがちなので、モック方針や前提データの作り方は人間が指示します。

DB を絡める場合は、テスト用のトランザクションでロールバックする、コンテナで使い捨ての DB を立てるといった土台を先に整え、AI にはその枠組みの中でケースを書かせると安定します。

E2E テスト

ブラウザやアプリを通してユーザー操作を再現する、最も重く壊れやすいレイヤーです。AI を使うと操作シナリオは速く書けますが、セレクタの脆さや待機処理の不備でフレーキー (実行のたびに結果が揺れる) になりやすい点に注意が必要です。

E2E は本数を絞り、課金・申込・ログインといったクリティカルパスだけに限定するのが鉄則です。AI には「主要導線を 1 本通す最小シナリオ」を書かせ、安定させてから少しずつ広げます。網羅は下層のユニット・結合に任せ、E2E は「壊れたら致命的な経路だけ」と割り切ると、メンテナンスコストが跳ね上がりません。

テストファースト × AI の具体手順

テストを AI に書かせる流れの中でも、品質を最も引き上げやすいのがテストファースト、つまり実装より先にテストを固定するやり方です。先にテストがあれば、AI に実装を任せても「テストが通る」という明確なゴールができ、実装の方針がぶれません。AI が仕様を勝手にすり替えるのを防げるのも大きな利点です。

実務では、おおむね次の手順で進めます。

  1. 人間が、追加する機能の仕様と受け入れ条件を言語化する
  2. その仕様をもとに、AI に失敗するテスト (Red) を書かせ、人間がケースの妥当性をレビューする
  3. テストを通す実装 (Green) を AI に書かせる。テストは固定したまま動かさない
  4. グリーンになったら、AI と一緒にリファクタリングする。テストが緑のままであることを安全網にする
  5. 抜けている境界値や異常系を AI に追加で列挙させ、テストを厚くする

ここで重要なのは、テストを実装に合わせて書き換えないという規律です。実装が通らないからとテストを緩めると、テストファーストの意味が失われます。テストは仕様の固定点であり、変えるべきは実装のほうだ、という前提を CLAUDE.md などのプロジェクト規約に明記しておくと、AI もその規律を守りやすくなります。テストファースト全体のフローやアンチパターンは AI 駆動 TDD で詳しく解説しているので、ループ設計を深掘りしたい場合はそちらも参照してください。

AI が書くテストの落とし穴と対策

AI に書かせたテストには、人間が書くものとは違う特有の癖があります。レビューで重点的に見るべき落とし穴を挙げます。

実装をなぞるだけのトートロジー。最も多いのが、実装の挙動をそのまま期待値にコピーしたテストです。たとえば内部で計算した結果を、そのまま期待値として書いてしまうと、計算ロジックが間違っていてもテストは通ります。対策は、期待値を「仕様から独立して」求めること。AI に期待値を計算で導かせず、人間が仕様から定めた値を使うよう指示します。

アサーションが薄い、または無い。実行はするが何も検証していない、あるいは「エラーが出ないこと」しか確認していないテストです。カバレッジ数値だけが上がり、バグを検出しません。対策として、生成テストに対し「わざとバグを 1 つ入れたら、このテストは落ちるか」を問う習慣を持ちます。落ちないなら、そのテストは仕事をしていません。

過剰なモックで本物の挙動を検証していない。AI はテストを通すためにモックを多用しがちで、結果として「モックがモックどおりに動くこと」を確認するだけのテストになることがあります。モックの境界は人間が設計し、少なくとも結合テストでは実物に近い経路を 1 本通すようにします。

フレーキーなテスト。時刻・乱数・並行処理・外部依存に起因して、結果が揺れるテストです。CI で赤信号が常態化する最大の原因になります。時刻や乱数は固定化 (フェイク注入) し、外部依存はモック、非同期は明示的な待機にする、といった土台を整えます。

これらの多くは AI を批判する話ではなく、AI が書いたものを人間がどうレビューするかの設計の問題です。チェック観点を明文化し、AI 自身にもセルフレビューさせると、検出率が上がります。

カバレッジの考え方とレビュー

カバレッジは便利な指標ですが、目的化すると害になります。AI は行カバレッジを埋めるテストをいくらでも書けるため、カバレッジ 100% を目標に置くと「実行されたが検証していない」テストが量産されるだけになりがちです。

私たちはカバレッジを「危険な箇所が薄くなっていないかを探す地図」として使います。全体を一律の数値で縛るのではなく、課金・認証・権限・データ更新といったクリティカルパスを重点的に厚くし、ログ出力や単純な getter のような低リスク領域には深追いしません。

実効的な品質を測りたいときは、ミューテーションテストが有効です。コードにわざと小さな変更 (バグ) を注入し、それを検出できるテストがあるかを調べる手法で、「カバレッジは高いが検出力が低いテスト」をあぶり出せます。AI が量産したテストの実力を測るのに、行カバレッジより信頼できる指標になります。

レビューでは、テストの追加そのものを歓迎しつつ、次の観点を見ます。何を保証しているテストか一読して分かるか、アサーションが意味を持っているか、実装に過剰結合していないか、壊れやすい固定値に依存していないか。レビュー観点の切り分け方は AI 生成コードのレビュー設計 で詳しく整理しているので、テスト以外のコードレビューも含めて仕組み化したい場合に役立ちます。

CI への組み込み

テストは CI で自動実行され、マージの条件になって初めて品質ゲートとして機能します。AI が大量にテストを生成しても、それが手元でしか動かなければ意味がありません。

組み込みの順序として、まず lint・型チェック・ユニットテストを PR マージの必須チェックにします。これらは速く安定して回るため、最初のゲートに適しています。次に結合テストを追加しますが、外部依存はモック化し、DB はコンテナや使い捨て環境で安定実行できるようにしておきます。E2E は実行が重いので、本数を絞ったうえで、夜間や特定ブランチでのみ回すといった分離も検討します。

フレーキーなテストを CI に入れると、赤信号が常態化してチームがテストを信用しなくなり、ゲートが形骸化します。安定しないテストは一旦隔離し、原因を直してから戻す運用にしたほうが、CI 全体の信頼を守れます。土台が安定してから、カバレッジ計測やミューテーションテストといった上位のチェックを段階的に足していくと、CI が無理なく育ちます。

AI 一次レビューを CI に組み込み、人間レビューの前段で機械的な指摘を潰しておくと、テストと合わせて「壊れたものはマージ前に止まる」状態に近づきます。

fixit の品質ゲート構成例

参考までに、FIXIT が AI 駆動開発の実プロジェクトで採用している品質ゲートの構成を、一般化して紹介します。プロジェクトの規模やリスクに応じて足し引きしますが、考え方の軸は共通です。

第一段は、ローカルとエディタの段階です。型チェックと lint をコミット前に走らせ、明らかな問題を最も早い段階で潰します。AI に実装を任せる場合も、この段で赤いものは PR に上げない、という規律を CLAUDE.md に書いておきます。

第二段は、PR の必須チェックです。ユニットテストと型・lint を必須にし、これが緑でなければマージできない状態にします。あわせて PR サイズが膨らみすぎていないかも見ます。AI は短時間で大量のコードを生成できるため、生成・リファクタ・テストを別 PR に切るなどして、1 件あたりのレビュー負荷を下げる設計をします。

第三段は、結合・主要 E2E と AI 一次レビューです。クリティカルパスの結合テストと最小限の E2E を回し、Claude Code などによる一次レビューで機械的な指摘を先に処理します。人間レビューは、設計判断・ドメイン整合・セキュリティ境界・課金や副作用といった、機械では判断しにくい領域に集中させます。セキュリティ境界を具体的にどう守るかは AI 駆動開発のセキュリティ設計 — 生成コードのリスクと対策 で、認可漏れやシークレット管理のパターンとあわせて解説しています。

第四段は、継続的な計測です。カバレッジの推移とクリティカルパスの厚み、フレーキー率を定期的に見て、テスト群が育っているか、形骸化していないかを確認します。検出力に不安が残るモジュールについては、ミューテーションテストも併せて確認します。

この構成のねらいは、「人間が毎回コードを精読しなくても、ゲートを通れば一定の品質が保証される」状態に近づけることです。完全なノーレビューを目指すわけではなく、機械が保証できる範囲を最大化し、人間の判断を本当に必要な箇所へ寄せる。テストの自動生成は、その機械側の保証を厚くする中核の手段になります。

まとめ

生成 AI によるテスト自動化は、テストの「量」を一気に増やせる強力な手段です。一方で、量がそのまま品質になるわけではありません。仕様は人間が決め、ケースの列挙とコード化を AI に任せること、実装をなぞるだけのテストを避けること、カバレッジ数値を目的化せずクリティカルパスを厚くすること、フレーキーなテストを CI に持ち込まないこと。この基本を押さえれば、AI のスピードを品質の向上にそのままつなげられます。テストファーストと組み合わせ、CI と品質ゲートで支える設計まで揃ったとき、AI 駆動開発は速くて壊れにくい開発に近づきます。

AI にテストを書かせて開発を加速させたいが、品質まで担保できる仕組みをどう作ればよいか迷っている、という方は、ぜひ FIXIT へご相談ください。レイヤー別のテスト設計から CI と品質ゲートの構築まで、AI 駆動開発のクリエイティブスタジオとして実装目線で伴走します。