AIコーディングエージェントを足がかりに開発者テストを導入しつつあるチームと話していて、何を確認したいのかが曖昧なままテストを書こうとしているように感じました。 その背景には、テストの目的を「バグをみつけること」と狭く捉えることに起因する掘り下げ不足がありそうです。 そこで、テストの役割についてもう一歩踏み込んで考えるための知見をまとめてみました*1。
手動・自動、テストレベル(ユニット/統合/システム(E2E)テスト)に限定しない、テスト全体の話です。
テストの目的
『JSTQB認定テスト技術者資格試験シラバス Foundation LevelのVersion 2011*2』では、テスト*3の目的として次の4つが挙げられています。
- 欠陥を摘出する
- 対象ソフトウェアの品質レベルが十分であることを確認する
- 意志決定のための情報を示す
- 欠陥の作りこみを防ぐ
このうち「欠陥(バグ)を摘出する」を重視しがちですが、「対象ソフトウェアの品質レベルが十分であることを確認する」つまり要求や仕様どおりに動作することを確認し、リリース可否などの「意志決定のための情報を示す」こともテストの大きな目的です。
また、テストや品質保証活動を開発の早い段階から実施し、欠陥の作りこみを防いだり早期に摘出したりする取り組みは「シフトレフト」と呼ばれ、重要視されています*4。
目的に応じて、取れる手段を考えてみましょう。
バグの摘出にはAIエージェントによるレビューも活用できる
バグにも色々ありますが、コードの書き方や仕様書との整合性に起因するものの中には、AIエージェントによるレビューで発見できるものもあります*5。 特に、コードを実行せずに発見できる欠陥については、AIエージェントによるレビューに任せ、動的テストを省略するという判断もできます。 投資対効果(ROI)を考えれば、検証観点によってはレビューで代替する選択肢もあってよいのではないでしょうか。
ただし、AIに参照させる仕様書が整備されていることが前提ですし、LLMは確率的な性質をもつため、実行ごとに指摘内容が変わる不安定さを許容しなければなりません。
また、手を尽くしても、AIによるレビューであらゆるバグを摘出できるわけではありません。 しかしここではいったんバグの摘出を主目的から外して、テストの役割を再考してみます。
開発をサポートする自動テスト
バグ摘出のためではなく、開発を円滑に進めるためにユニットテストや統合テストを活用します。
- 完了の定義として:テストがパスしていることで「仕様を満たしていると判断できる」のであれば、AIエージェントに与えるゴールとして使えます(テストファースト*6)
- リグレッションテストとして:追加されたテストは、以降の変更によるリグレッション(退行、デグレード)から保護してくれます
テストコード(スクリプト)による自動テストはLLMと異なり、決定論的に動作するよう設計できます*7。 仕様から導いた振る舞いを同じ基準で繰り返し検証できることは、イテレーティブな開発スタイルにおいて大変役に立ちます。
以下、補足です。
仕様のテストを書く
重要なのは、仕様をもとにテストコードを書くことです。 すでにあるコードをもとに実装のテストを書いてしまうのは、AI以前からユニットテストのアンチパターンです*8。 実装の誤りをそのまま正解とするテストになるだけでなく、実装の詳細に依存したテストは壊れやすく、リグレッションテストとしてのROIも下がります。
壊れやすいテストが増えてくると、以前はメンテ不能になって放棄されていたものですが、今はAIがトークンを無駄に消費してメンテしてくれます。 これは意識していないと気付きにくい問題です。
また『Investigating Test Overfitting on SWE-bench』という論文では、LLMの生成した不完全なテストを使ってコードを反復修正していくと、そのテストにはパスするものの、実際には問題を解決できていないパッチを生成してしまうケースが示されています。 AIエージェントにとって、テストがパスすることは明確なゴールになります。だからこそ、与えるテストが正しい仕様を表現しているかが重要です。
テスト技法を活用する
仕様からテストケースを作成するにはテスト技法(テスト設計技法)が役立ちます。 プロダクトコードの実装前に設計が必要なように、テストケースもテスト設計を経て作ります*9。
また、テスト技法によるモデリングには仕様の曖昧さや考慮漏れをあぶり出す効果もあり、「欠陥の作りこみを防ぐ」につながります*10。
テスト技法を学びたいかたにはこちらの書籍がお勧めです。
UIのテストも書く
UI(レイアウトや操作)のテストは、テストコードの作成や保守にコストがかかる割に効果を得にくいため、目視確認に頼っていた領域も多いでしょう。 しかし、AIコーディングエージェントに与えるゴールとして考えると、自動化する価値が高まります。 押せるべきボタンが画面外にあったり、他のコンポーネントに隠れていたりして押せないなどは、テストコードで機械的に検出できると捗ります *11 *12。
統合テストに位置づけて実施しており、ユニットテストで検証された部品同士を統合(結合)して機能することを検証するのが目的です。 網羅的な検証は実行の早いユニットテストに任せ、UIテストでは主要な操作経路とコンポーネント間の連携を確認します。
テストコードの保守性の問題
たとえ仕様をもとにテストを書かせても、AIエージェントはテストコードを書きすぎる傾向があります。 またそもそも保守性の低いコードを書きがちで、テストコードとしては看過できない特性です。
具体例として、Slay the SpireクローンをすべてAIエージェントに作らせたときのcode : test ratioは1 : 5.0でした。 テストコード量に適正な比率があるわけではありませんが、私が普段めやすとしている1 : 1.0〜2.0と比べるとかなり多く、統合テストを含むとはいえもっと減らしたいと考えています。
保守性についてはスキルや静的解析(アナライザーやLint)である程度は改善できていますが、まだ試行錯誤しているところです。
QA担当者によるテスト
開発者テストで仕様どおりに動作することまで確認できていれば、QA担当者によるシステムテストはより高い目線で実施できます。 見た目・手触り感、また大局的な観点などは仕様書やコードのレビューでは十分に評価できないため、そういった問題の摘出も期待されます。
もちろん、QA担当者が開発者とは異なる観点で仕様書ベースのテストを実施する価値はあります。 この手のテストは、継続的に繰り返し実行するものであればスクリプトによる自動化を検討すべきですが、1〜2回しか実施しないのであれば手動テストやAIエージェントに操作させてもよいでしょう*13。 ROIを考えて選択しましょう。
必要なのはテスト戦略
万能なテスト手段というものはありません。目的とする品質を定め、複数のアプローチを組み合わせてカバーする*14「テスト戦略(test strategy)」を立てることが必要です。 テスト戦略は、開発・QAで個別ではなく、プロジェクト全体で考えましょう。
また、あえてやらないテストを決めるのも戦略です。 AIによってテストコードの生成コストは下がりましたが、だからといってテストを増やすことが最適とは限りません。 一方、AIによるレビューなど、従来より低コストで利用できる検証手段も増えています。何を確認したいのかを明確にし、目的に応じて手段を選択することが重要です。
第5戒──自動化しろ。これは最終段階だ。ネバダでもフリーモントでも、一番のまちがいは、ステップの自動化から始めてしまったことだ。要件をすべて洗い直し、部品や工程を減らせるだけ減らし、バグをつぶし切るまで自動化は待たなければならない。
そう、イーロン・マスクも言っていました*15。
参考
自動テストの特性については、こちらの8原則も参照してください。
こちらの同人誌も参考になるはずです。
Unityにおけるユニットテストの書き方について書いた同人誌です。テスト技法についての章もありますので、Unityで開発しているのであればまずこちらから入ることをお勧めします。
UnityにおけるAIコーディングエージェントを使ったテストファースト開発、テスト設計を含むスキルを公開しています。
*1:今後支援先で「これ読んで」する用
*2:最新版ではより広い視点で9項目が挙げられていますが、テストの目的がシンプルに表現されている2011年版から引用しました
*3:広義のテスト活動の意で、ドキュメントレビューや静的解析も含む
*4:「シフトレフト」は2001年に提唱された言葉ですが、テストを開発の早い段階から実施するという考え方はそれ以前から存在していました(「Wモデル」など)
*5:レビューで確認すべき観点を指示する際は、同値分割法、境界値分析、状態遷移テスト、エラー推測などのテスト技法(後述)が役立ちます。なお、AIは言葉は知っていても実践できるとは限らないので、噛み砕いて伝えるようにしてください
*6:工程で考えると 仕様→実装→テスト なので、テストを先に書くことは逆転しているように見えますが、抽象度で考えれば 仕様→テスト→実装 は自然です
*7:スクリプトの書きかたによっては不安定なフレーキーテストになるので注意
*8:実装から仕様を抽出して仕様のテストを書かせられれば話は変わってきますが、難しそう。私は必要でないので取り組んでいません
*9:慣れると脳内でやってしまいますが
*10:形式手法も活用できますが、本稿では割愛します
*11:私はビュー(MVCのView)相当をAIエージェントに書かせているため、レイアウト上の重なり・はみ出しなども機械的に検出させています。完全なレイアウトを検証するテストは壊れやすいため非推奨です
*12:レイアウトは、スクリーンショットを画像解析して検証させることも効果的です。ただしテスト実行のたび行なうとコストが高くなるため、実行契機は絞るとよいでしょう
*13:LLMの推論によるテスト実行は、スクリプトベースの自動テストよりも手動テストに近い特性をもちます。「自動化」でひとくくりにしないことをお勧めします
*14:複数のレイヤーを重ねる考え方は「スイスチーズモデル」や「DevOpsバグフィルター」として知られています
*15:引用は生産ラインの話なので「バグをつぶし切る」は本稿にはそぐわないのですが、原文のまま





