AIはネガティブテストケースを生成できるか?

Zeshi Du
AIはネガティブテストケースを生成できるか?カバー画像

できます。しかし、本当に価値のあるネガティブテストケースは、多くのAIツールが生成するものとは異なります。

AI生成によるネガティブテストの最も簡単な形はこうです。コードを読み込み、バリデーションルールを特定し、各ルールが拒否すべき入力を正しく拒否することを確認するテストケースを生成する。高速で体系的ですが、範囲が狭い。ハッピーパスの鏡像をカバーするにすぎません。実際にユーザーに到達する障害モードはカバーしません。

重要なネガティブテストケースは、実際のユーザーが問題に直面したときに行う操作を再現するものです。権限のないアクションを試みること。存在しなくなった依存関係を持つリクエストを送信すること。単独では正常に動作するが、2つのレイヤーが何が有効かについて意見が食い違うときに失敗するシーケンスをトリガーすること。開発者が予期しなかった状態にプロダクトを追い込み、何が起きるかを観察すること。

これらのテストケースを生成するには、コードレイヤーではなく、プロダクトレイヤーで操作する必要があります。

ネガティブテストが本当に何のためにあるか

ネガティブテストは特定の問いに答えます。何かが問題になったとき、プロダクトはどう振る舞うか?

この問いには多くの次元があります。入力バリデーションに関するもの:データが誤っているとき何が起きるか?認可に関するもの:ユーザーに権限がないとき何が起きるか?シーケンスに関するもの:ユーザーが想定外の順序でアクションを取るとき何が起きるか?状態に関するもの:開発者が十分に予期していなかった状態にシステムがあるとき何が起きるか?

コードレイヤーのネガティブテストは最初の次元をある程度うまく処理できます。バリデーション関数が不正な入力を拒否することを確認できます。残りの3つの次元は、実際にプロダクトを悪条件下で動作させ、その結果を観察する必要があります。

認可の失敗はバリデーションロジックには現れません。ユーザーが必要な権限を持たない実際の認証情報で、実際のリソースに対してアクションを試みるときに現れます。シーケンスの失敗は個々の関数テストには現れません。ユーザーがステップ2の前にステップ3を完了したり、ステップ4を完了した後にステップ1に戻ったりするときに現れます。状態の失敗はユニットテストには現れません。開発者がコードを書く際に十分にモデル化していなかった条件下でユーザーが画面に到達するときに現れます。

これらをテストするには、プロダクトをナビゲートし、悪条件を作り出し、何が起きるかを観察するエージェントが必要です。

TestSpriteが本物のネガティブテストケースを生成する方法

TestSpriteは、実際のユーザーや綿密なQAエンジニアのように、悪条件下で動作中のアプリケーションを探索することでネガティブテストケースを生成します。

他の検証ツールはコードを読んで推測します。TestSpriteはアプリを開いて実際に使用します。

Claude Code、Cursor、Windsurf、またはMCP対応のAI IDE内のTestSprite MCPサーバーを通じて、単一の指示で探索が始まります。TestSpriteの並列エージェントがライブプロダクトをナビゲートし、境界を意図的に探ります。ブロックされるべきアクションを試み、拒否されるべきリクエストを送信し、想定外の順序でフローをナビゲートします。

生成されるネガティブテストケースは、コードの拒否ロジックを読み取ることから導き出されたものではありません。失敗するはずのことを試み、プロダクトの応答を観察した際にエージェントが確認した内容から導き出されたものです。

ネガティブテストドメインとしての認可

認可の失敗はネガティブテストの最も重要なカテゴリの一つでありながら、最も不十分にテストされることが多いカテゴリの一つです。

フロントエンドには存在するがバックエンドには存在しない権限チェック。制限されたユーザーがURLに直接アクセスすることで到達できる管理者アクション。あるユーザーが別のユーザーに属するリソースにアクセスできる状況。特定のロールを持つユーザーのみリクエストを受け付けるべきなのに、認証済みユーザーであれば誰でもリクエストを受け付けてしまうAPIエンドポイント。

TestSprite のエージェントは、各関連ロールの実際の認証コンテキストでプロダクトを操作します。各ロールがブロックされるべき操作を、UI レイヤーと基盤となる API の直接呼び出しの両方で試みます。制限されたユーザーが本来実行できないはずの操作を実行できた場合、それはネガティブテストの失敗として精確な説明とともに報告されます。試みた操作、試みたロール、ブロックされるべきだった内容、そして実際に起きたことが明示されます。

これは、コードインスペクションでは生み出せないネガティブテストです。コードインスペクションは権限ロジックが存在することを確認します。プロダクトレイヤーのテストは、その権限ロジックが実際の条件下で正しく機能することを確認します。

シーケンスと状態をネガティブテストのドメインとして

シーケンスと状態に関するネガティブテストケースは、開発者が意図して設計していなくても、実際のユーザーが時として辿るフローを再現する操作を必要とします。

既に完了した注文に対してユーザーが支払いを送信しようとした場合はどうなるか。有効期限が切れた招待をユーザーが承認しようとした場合はどうなるか。途中で中断したマルチステップフローに戻り、ステップ 2 を再入力せずにステップ 3 から完了しようとした場合はどうなるか。

TestSprite のエージェントは、不正なシーケンスを構築することでこれらの状況を検証します。リソースを作成してから本来あってはならない状態でそれを操作しようとしたり、フローを順序通りでなく実行したり、完了済みのプロセスに戻ったりして、プロダクトがどのような挙動をするかを観察します。

この探索から生まれるネガティブテストケースは事前定義されたものではありません。発見されるものです。エージェントはプロダクトが追い込まれる可能性のある状態を見つけ出し、その状態に至ったときに何が起きるかをテストします。

API ネガティブテスト:バリデーションロジックを超えて

API レイヤーにおけるネガティブテストケースは、入力バリデーションをはるかに超えた範囲に及びます。

必要なリソースが存在しない場合、エンドポイントはどう振る舞うか。別のユーザーに属する ID をリクエストが参照している場合はどうなるか。そのエンドポイントを呼び出す権限を持たないロールの有効なトークンとともにリクエストが届いた場合はどうなるか。マルチステップ操作の途中で中断され、その後リトライされた場合はどうなるか。

TestSprite の Backend Testing 2.0 は、ポジティブテストケースと同じ方法で API ネガティブテストケースを生成します。テスト計画を生成する前に、エージェントは有効な入力でエンドポイントを呼び出してベースラインを確立します。その後、境界を探索します。存在しないリソースへのリクエスト、権限不足のリクエスト、API の期待するシーケンスに違反するリクエストを送信します。

生成されるネガティブテストケースは、不正な条件下での実際の API 動作から得られたアサーションです。API が 404 を正しく処理して特定のエラー構造を返す場合、テストはその構造を検証します。未認可のリクエストに対して API が 403 を返すべき場合、テストはコードの拒否ロジックに対してアサートするのではなく、実際のレスポンスコードを確認します。

シナリオ:ネガティブテストが認可の欠陥を発見する

ある開発者が Cursor を使ってドキュメント共有機能を構築しました。ドキュメントは特定のユーザーと特定の権限レベル(閲覧・コメント・編集)で共有できます。実装は正しく見えます。権限チェックも存在します。

TestSprite のエージェントはネガティブな意図を持ってこの機能を調査します。あるユーザーとしてドキュメントを作成し、それを閲覧のみの権限で別のユーザーと共有します。そして閲覧専用ユーザーとしてすべての操作を試みます。ドキュメントの閲覧(成功すべき)、コメント(失敗すべき)、編集(失敗すべき)、削除(失敗すべき)、共有設定の変更(失敗すべき)。

UI は閲覧専用ユーザーのコメント・編集・削除・共有変更を正しくブロックします。次にエージェントは閲覧専用ユーザーの認証情報を使って API エンドポイントを直接呼び出します。

削除エンドポイントはリクエストを受け入れ、200 を返します。閲覧専用ユーザーは API を直接呼び出すことで、UI の制限を回避してドキュメントを削除できてしまいます。権限チェックはフロントエンドコンポーネントに存在していました。API ルートハンドラーには実装されていなかったのです。

これこそが重要なネガティブテストケースです。コードインスペクションはフロントエンドの権限チェックが存在することを確認したでしょう。プロダクトレイヤーのネガティブテストによって、バックエンドが同じルールを適用していないことが発見されました。

失敗は構造化された形式で Cursor セッションに返されます。修正は同じセッション内で行われます。

まとめ

AI はネガティブテストケースを生成できます。価値あるテストケースは入力バリデーションを超え、実際にユーザーへ影響する障害モードをカバーします。すべてのレイヤーで適用されていない認可の境界、ユーザーが期待通りのパスを辿らない場合に壊れるシーケンス、不正な条件下でプロダクトが追い込まれる可能性のある状態、そして拒否されるべきリクエストに対する API の振る舞いです。

TestSprite は、入念な QA エンジニアや新機能を探索する好奇心旺盛なユーザーと同じように、不正な条件下でライブプロダクトを操作することでネガティブテストケースを生成します。エージェントは失敗すべき操作を試み、実際に何が起きるかを観察し、意図した動作と実際の動作のギャップを明らかにします。

このプロセスから生まれるネガティブテストケースは、コード内の拒否ロジックを読み取ることで導き出されるものではありません。プロダクトを実際に動かし、追い込まれたときにどう振る舞うかを観察することで導き出されます。

今すぐ AI IDE 内の TestSprite でリアルなネガティブテストケースの生成を始めましょう。