AI自動テストの意味その1:テストを自動化するAI
プロダクトから生成されるカバレッジ、見た目の変更で壊れないよう意図として表現されるステップ、修正する側が使える形で返される失敗。テスト対象のソフトウェアは通常の決定的なものであり、AIはツール側にあります。
これはこのカテゴリのほとんどの製品が提供しているものであり、ほとんどのチームが必要としているものでもあります。
意味その2:AIを内包するシステムをテストする
こちらでは、プロダクト自体が非決定的です。同じ入力から異なる出力が返るため、「期待値と実際の値が一致する」という判定が使えなくなり、別の種類のアサーションが必要になります。
等価性ではなく、性質
出力が正しい形式になっているか、出典を示しているか、長さの範囲に収まっているか、拒否すべきものを拒否しているかをアサートします。
単発の実行結果ではなく、分布
1回の実行からわかることはほとんどありません。何度も実行し、その割合を追跡します。
絶対値ではなく、リグレッション
問うべきは、完璧かどうかではなく、この変更によって悪化したかどうかです。
どちらにも共通する間違い
そのチェックが失敗し得ることを一度も確認しないまま、チェックが通ったことに意味があると思い込むことです。決定的なケースでは、決して赤くならないアサーションだらけのスイートができあがります。非決定的なケースでは、何を入れても高いスコアを付ける評価ハーネスができあがります。
意図的に何かを壊してみてください。1分あれば済みますし、どちらの種類のチェックであれ、それが測定すると称しているものと実際につながっている証拠は、これしかありません。
混在したプロダクトで境界を引く
AIを内包するプロダクトの大部分は、実際にはAIではありません。有効なのは、非決定性が広がるに任せるのではなく、明示的に線を引くことです。
その機能を取り巻くものは、すべて通常のソフトウェアです。認証、ストレージ、レート制限、出力を描画するインターフェース。いずれも従来どおりにテストできますし、1つのコンポーネントがそうだからといってプロダクト全体を予測不能なものとして扱えば、安価で信頼できるカバレッジを大きく失うことになります。
境界の内側では、性質と割合に切り替えます。入力が入り、出力は変動します。そこでアサートするのは、正しい形式になっていること、実在するものを出典として示していること、拒否すべきものを拒否していることです。この境界がどこにあるのかを一度書き出しておくこと。それが、決定的な部分を統計的な手法で過剰にテストしたり、厳密なアサーションが失敗し続けるせいでAI部分のテストが手薄になったりする事態を防ぎます。
自分たちのケースはどちらか
2回実行して同じ答えが返るプロダクトなら前者のケースであり、動作中のアプリケーションに対して生成されたカバレッジが必要です。そうでないなら後者であり、合否ではなく、性質ベースのアサーションと割合が必要になります。
両方に当てはまるプロダクトも数多くあります。決定的なアプリケーションの中に、AI機能が1つ入っているようなケースです。決定的な部分は通常どおりテストし、AI機能は1つのアプローチを両方に引き伸ばすのではなく、独立した課題として扱ってください。
ターミナル
npm install -g @testsprite/testsprite-cli
testsprite setup
ローカルにインストールしたくない場合は、ダッシュボードでも同じ範囲をカバーできます。コマンドの全体像は CLIリポジトリにあります。
方法は2つあり、その選択は結局のところ、誰がパイプラインを所有するかの問題です。ダッシュボードから GitHub App を接続する場合、リポジトリへの変更はいっさい不要です。ビルドがすでに発行しているデプロイに反応するためです。一方、 GitHub Actions のステップを追加すれば、チェックはリポジトリの中に置かれ、ビルドの他の部分と同じようにレビューされます。
TestSpriteが扱うのはどちらの意味か
前者です。TestSpriteはAIを使って通常のソフトウェアを検証します。プロダクトから生成されるカバレッジ、意図として表現されるステップ、デプロイ済みアプリケーションに対する実行、そしてコーディングエージェントが対処できる形で返される失敗です。
AI機能を含むプロダクトであれば、その機能の周囲にあるすべて、つまりプロダクトの大部分をカバーします。認証、ストレージ、レート制限、インターフェース、ユーザーが実際にたどるフローです。API側の状態にまつわる問題は、Auto-Authentication、Dynamic Variables、Dependency Chains、Auto-Cleanupが処理します。
機能そのものには性質ベースのアサーションと割合が必要で、これは別のハーネスの領域です。この境界を明示的に引くからこそ、プロダクト全体を予測不能なものとして扱うのではなく、決定的な大部分に対して安価で信頼できるカバレッジを得られます。
TestSpriteが行うのはどちらですか?
前者です。動作中のプロダクトに対して、決定的なアプリケーションの挙動を検証します。たまたまAI機能を含んでいるアプリケーションも対象です。
LLM機能はどのようにテストすればよいですか?
性質ベースのアサーションを何度も実行し、単発の結果ではなく割合を追跡します。回答の品質よりも、拒否、フォーマット、出典の有無のほうが通常はチェックしやすい対象です。
同じテストスイートで両方をカバーできますか?
決定的な部分についてはカバーできます。非決定的な機能には、合格とは何かという独自の基準を持つ、専用のハーネスが必要です。
AI機能の合格率はどのくらいが妥当ですか?
それまでの自分たちの合格率です。ベンチマークから借りてきた絶対的な目標値が、自社のプロダクトにそのまま当てはまることはめったにありません。
1回の失敗はバグですか?
非決定的な機能では、それだけではバグとは言えません。シグナルになるのは動いた割合であり、1回の実行はノイズです。