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はネガティブテストケースを生成できます。本当に価値があるテストケースは、単純な入力バリデーションにとどまらず、実際にユーザーへの影響が生じる障害モードをカバーします。すなわち、すべてのレイヤーで適切に適用されていない認可の境界、想定された手順に沿わない場合に破綻するシーケンス、adversarialな条件下でプロダクトが陥り得る状態、そして拒否されるべきリクエストに対するAPIの挙動などです。

TestSprite は、細心の注意を払うQAエンジニアや好奇心旺盛なユーザーが新機能を検証するのと同様に、adversarialな条件下で実際のプロダクトをナビゲートすることでネガティブテストケースを生成します。エージェントは失敗すべき操作を試み、実際に何が起きるかを観察し、意図した動作と実際の動作のギャップを明らかにします。

このプロセスから生み出されるネガティブテストケースは、コード内の拒否ロジックを読み解くことで導き出されるものではありません。実際にプロダクトを動作させ、負荷をかけた際の挙動を観察することから導き出されます。

今すぐAI IDEから TestSprite を使って、リアルなネガティブテストケースの生成を始めましょう。