本記事では、ウェブアプリケーション開発現場でのテストの実態と、ソフトウェアテストにLLM(AIエージェント)を利用することの可能性という、(あまり関係のない)2つのトピックについて考えてみる。
書いている人
ぼく自身は、あくまで主観ではあるけど、昨今のウェプアプリケーション開発に必要とされるスキルをだいたい一通り身につけた、たぶん平均的なソフトウェアエンジニアだと思う。ベテランではあるので、いろいろな現場を経験して、世間がどんな感じで開発しているのかのイメージを持っている。ただし、業界は偏っていて、スタートアップや小規模な開発プロジェクトしか経験がない。規模としては数人〜多くて十数人。開発ライフサイクルの全工程についてエンドツーエンドでめんどうを見る。逆にSIer的なエンプラ開発の現場は話でしか知らないので、そういう意味では偏りがあると思う。アプリケーション開発技法については山程学んだけど、テスト設計だとか品質保証の技法そのものについてはろくに学んだことがない。
テスト何もわからない……
何のためにテストをするのか
先に進む前に、まず、そもそも我々は何のためにテストをするのかというところから確認しておきたい。
我々ソフトウェアエンジニアがやっていることは、第一義的には、ユーザーが使えるソフトウェアの機能を開発して、それを届けることである。そして、テストはその目的のための欠かせない一部ではある。けれどもあくまでテスト自体は手段であって目的ではない。つまり、ソフトウェアの機能が届くのであればテストは端折れるかもしれないが、その逆は成り立たない1。個人的には、テストの目的とは、ソフトウェアが意図した通りに動くという自信を持つことだと思っている2。そして、エンドツーエンドで、品質保証上一番の自信をもたらしてくれることというのは、作ったものを実際にユーザーが使うのと同じように手で動かしてみること、いわゆるマニュアルテストだと思う。一度も手動のスモークテストをせずにコードをチェックインするプログラマーはあまりいないはずだ3。ミクロな単位で自信を持つための手法として、レッド→グリーンのサイクルで回すTDDもあるけど、これはエンドツーエンドに適用するのが難しい。テスト自動化スクリプトが明瞭に書かれていれば、それが何を確認するためのものなのか読んで理解はできるが、すくなくとも一回は動かしてみないと、正しいテストになっているのか確証は持てないと思う。コードというのは動かしてみるまでわからない、言い換えると人間のコード把握能力には限界があるので。
しかしながら、いかにマニュアルテストが、ソフトウェアが意図通り動くことへの大きな自信を与えてくれるとは言え、実行コスト、手順の正確性、網羅性などの問題から、それだけでは開発ライフサイクルを回すには不十分なので、さまざまな自動化が必要になってくる。そうして我々は、マニュアルテスト以外に、ユニットテスト、E2Eテストなどの自動化された繰り返し実行できるテストを実装することになる。
ふつうのウェブ開発のテストの実態
これは偏見かもしれないけど、平均的なウェブエンジニアというのは、プログラミング言語とか、フレームワークとか、設計技法とかには非常に強い興味を持っているけれど、テストそのものにはそれほど関心がない(ように見える)。TDDやDIは人気のトピックのひとつではある。けれど、あくまで開発技法として興味を持たれているのであって、テスト自体をどのように設計するかとかの話ではない。実際、ケント・ベックのTDD本とかでも、テストの内容については、ある意味行き当たりばったりで、直感的に決定している。それは、TDDの関心が、今開発している目の前の機能が正しく動いていることに自信を持つことだから、自然なことではある。たぶん、平均的なウェブエンジニアは、テストそのものの内容なんてそんな深く考えなくても自明だろ、ぐらいに考えているような節さえある。結果として、多くのソフトウェアプロジェクトで、テストというのは、まともに「管理」されていない。いままで関わった現場で、テストそのものの管理をまじめにやっている現場なんて、まじで一個もない。良くて、コードカバレッジという動態としては追跡されてはいても、その内容や質というところまでは把握されていない。4
一方で、ぼくのあまりよく知らない、QAと呼ばれる人達の関心は、まったく異なっているようだ。QAの人達は、アプリケーションの仕様に基いてテストを分析・設計し、計画し、実装・実施する。そこでは仕様に対してテストが何%カバーできているかなどが重大な関心事となり、境界値やエラー時の振舞いなどについて入念にテストされる。結果として、システムの振舞いは隅々まで仕様で定義された挙動と一致することになる。これが高品質なソフトウェアの意味だ。ぼくが関わってきた現場なんて、動いているシステムがすべてであり、そもそも仕様書なんていうものからしてどこにもないんだから、まったく違う世界だ。
しかし、どうしてウェブ開発のテストというのはこうなってしまうんだろうか。思うに、上で記述したようなプラクティスは「均衡」なんだと思う。たしかに、多くのアプリケーションは、系統的にテストされないままリリースされている。開発者に課された主たるタスクは、(速く)機能を届けることであって入念に品質保証することではないので、できることならテストは雑に済ませてしまう方向へのインセンティブが常にある。だから、リリースされたシステムを隅々まで注意深く点検してみると、どこかしらしょうもないバグが残っている。きっとバックログにはマイナーな不具合が山ほど積み上がっているかもしれない。ときには、重大な見逃しがあってインシデントに繋がってしまったりすることさえあり、そういうときはほんとうに反省しないといけない。
テストが管理されていないのなら、システムの品質はどう担保されているのか。品質は、開発者のプログラミングスキル、コードレビュー、開発プロセスに大いに依存している。スキル・経験のあるプログラマーは、過去の経験からバグのパターンやベストプラクティスを知っているので、そもそもバグがあまり出ないように設計・実装することができる。直感で、書いておいたほうがいいテストコードを識別しカバレッジを確保する。また、スキル・経験のあるプログラマーはコードレビューで、きなくさい部分をキャッチできる。さらに、短い反復による開発プロセスは、トリアージと迅速な復旧により、露呈したバグのダメージを最小化する。これらがあるので、たとえテストが系統的に管理されておらずとも、そこまで悲惨な状況にならずにすんでいる。また、我々はアジャイルプロセスで開発を行うので、プロジェクトの置かれた状況はモニタリングされる。品質に問題があることが明確に認識されれば、プロセスの中で改善する作用が働き、なんらかの対策が実装される。すべての事象は優先度を振り分けられてキューに詰め込まれる。
テスト管理されていないことが致命的な問題として明確に認識されれば、プロセスの自浄作用によって修復されるはずだ。テストが管理されなくても問題として浮き上がってこないのであれば、たぶん問題ではないんだろう。言い換えると、楽観的に考えるのであれば、価値の低いテストは職人芸とプロセスを通じて適応的に落とされ、最適化されていると言うこともできる。これが「均衡」の意味だ。そして、どこで均衡するかは、もちろんチームやプロジェクトの文脈・環境によって異なる。
テストにLLM(AIエージェント)を活用する
LLMはもちろんテストにも利用できるけど、その利用のしかたはいろいろ考えられる。
まず一番素朴な利用のしかたは、コーディングエージェントにアプリケーションのコードを書かせたときに、ついでにテストコードも書かせる(あるいはエージェントが勝手に書く)ということだろう。このとき、とくべつ指示したり制約を与えてなければ、エージェントが勝手に(暗黙に)テスト分析や設計もする。LLMはランタイムの情報にはアクセスせずに、コードからアクセシビリティーIDなどを検出してテストを書く、あるいはテストに必要なフックがなければアプリケーションに足す。AIエージェントを使いはじめると、ほとんど自然にこういうことが始まるんではないかと思う。一般にLLMはテストケースを思い付くのが得意だと思われているし、実際かなり細かいケースまでカバーしてくれる。ここでたぶん起きがちなのは、テストコードはたくさん追加されているものの、それらはコミットした人自身を含め、あまりレビューされてはおらず、適切なのかどうか誰も知らないという状況。雑に書かれたテストコードの正確性なんて、ただでさえ分析するのがめんどうなのに、LLMがそれを大量に生成した日には、そんなのだれもまじめに時間をかけてレビューしたくはないだろう。結果、コードは増えてるけど、それらに何の価値があるのかはよくわからない。およそ呪術のような慣習がこの2026年に蔓延ることになる。運がよければ、それらの未管理自動化テストが後々リグレッションを検知してくれるかもしれない5。
別の最近出てきている方法は、自然言語でテストを記述して、LLMにそれを解釈させた上でツール呼び出しを通じてテスト対象アプリを操作するというもの。この手のツールに、playwright-cli/mcpや、appium-mcpなどがある。SaaSでも似たような概念のテスト用ツールはたくさんある。LLMは現在画面に表示されている内容のスクリーンショットを元にUIを叩くこともできるので、ふつうのテストではカバーが難しいことまでできてしまう可能性もある。これ系のツールは、2種類に分けられる。初回の実行はLLMが駆動するけど、そのときにテストコードも生成して、次回以降は生成されたコードで決定論的なテストを実行できるタイプのもの。つまりこれは、実行環境と相互左様しながら動作する、実質的にはテストコードジェネレータと言える。もう一つは、コード生成はしない、自然言語ベースの純粋なテスト実行エンジン。
ただし、LLMを介した実行環境の操作というのは、非常に遅い。そして、なんといっても高い。リグレッションテストのような頻繁かつ大量のテスト実行をすべてLLMを介して行うというのは、現状、速度的にも費用的にも課題がある。またLLMである以上、100%期待した動作を保証することはできないので、ミッションクリティカルな用途には使えないかもしれない。一方、多少の予期しない事態に遭遇しても非同期でタスクを遂行してくれるAIエージェントの性質は、うまくハマれば便利なことは間違いない。こういった形のLLMテスト実行エンジンが、オープンウェイトモデルでトークンコストを気にせず24時間稼動し続けてくれるようになれば、違った世界が見えてくるような気がする。一方、AIエージェントは非同期性(つまり人間の手がかからない)が最大のメリットであることを考えると、単に自然言語で入力として与えたテストシナリオを実行してくれるという設計だと、自律性のうまみがそれほど得られないような気がしている。人間が介入しなければならない余地が増えるので。個人的には、対象システムのURLとGitHubリポジトリへの権限を与えたら、勝手にシステムを探索・分析して、知識を蓄えた上で、(AIから発せられた質問に答える以外には)ほとんど人間が介入することなく、システムに問題がないことを自律的に確認・報告するところまで行って欲しい。それぐらいまでやってくれれば、「遅さ」は問題ではなくなると思う。
いずれにせよ、テスト実装・実行という文脈だけで言うと、最初に述べたアプリコードと同時にテストコードも書かせるやりかたで、現状十分な気はしている。テストを書くタイミングとしても一番いい。コーディングエージェントは、アプリの内部情報(コード)についても完全にアクセスできるし、何ならアプリ自体に(アクセシビリティーIDを追加するなど)介入することさえできる。LLMの膨大な出力をどう監査するかという問題は残るけど、それはいずれにしろ、どうにかしないといけない。ただし、このやりかたを実践するためには、テストを実施する人がアプリのコード自体にアクセスできることが前提なので、開発部隊とQA部隊が別れていてQAはコードを触れない、みたいな状況だとこれはできない。その場合、別の方法を取るしかない。
また、テスト実装・実行以外での活用方法として、テスト分析・設計をLLMに行わせて、テスト管理を行うということも考えられる。前述したように、ぼくはこれまであまりまじめにQAに取り組んだことがないので、プログラマーがアプリコードとテストコードを同時にかつアドホックに書くというスタイルで十分だと思っているんだけど、もし高品質なソフトウェアを求められていて、QAを系統的に行う必要があるような場合には、もっとまじめな方法を考えなくちゃいけないだろうし、LLMにテストを分析・設計させることを考えてもいい。これを支援してくれるLLMベースの SaaSプロダクト もある。
まとめ
- 平均的なウェブ開発現場では、あまり系統的なテストをしてないけど、なんとかなっている
- トークンにお金がかかるうちは、LLMにテストを直接実行させなくていいと思う(とくに開発者=QAなのであれば)
- 開発者とQAが分離されてたり、系統的なテストを行う必要があるのであれば、LLM活用の余地は増えそう
- もちろん、みんなそんなことをわざわざ表立っては言わないけど、観察していると暗黙にそのように考えて行動しているソフトウェアエンジニアは少なくないように見受けられる。自分自身を含め。 ↩
- 暗黙のサブゴールとして速くリリースすることというのもあり、これは自動化に関わってくる ↩
- リリースするまで動かすことが難しいケースを除く ↩
- 正確には、一度そのようなテスト管理を試みようとしたご近所のプロジェクトも見かけたけど、やがて興味を持たれなくなり放棄されたみたい ↩
- そしてAIエージェントがそのロジックの不具合を勝手に直すかもしれないし、あるいは間違っていたテストコードをAIエージェントがいつのまにか直しているかもしれない ↩