成功か失敗かだけでは不十分:14の判定がどのように決定されるか
テストの失敗(赤)は、アプリケーションが壊れていることを意味するはずです。しかし、赤がDNSの一時的な不調やCAPTCHAの表示、ブラウザのクラッシュも意味しうる場合、チームはエラーログを読む代わりにテストを再実行するようになり、真の欠陥はノイズの中に埋もれてしまいます。Nexus Studioは、すべての実行に2つではなく14の判定のいずれかを割り当てます。このページでは、エンジンがどのような順序で判定を選択するのか、そしてその手法にどのような限界があるのかを説明します。
執筆:Nexus Studioチーム(Verdict System LLC)。2026年10月7日。
14の判定(verdicts)とは何ですか?
14の判定(verdicts)は、SECURE、CHAOS_RESILIENT、AUTO_RECOVER、FLAKY、PERFORMANCE_DEGRADED、A11Y_VIOLATION、SECURITY_VIOLATION、BREACHED、BREACHED_FLAKY、CHAOS_BREACHED、TIMEOUT、UNREACHABLE、BLOCKED、CRASHED です。これらは、合格(passed)、条件付き合格(passed with a reservation)、アプリケーションの破損、および環境やテストハーネスに原因があるためアプリケーションの判定なし、の4つのグループに分かれます。
エンジンはどのように判定を決定しますか?
エンジンは次の順序で3つの質問を行います。
- テストはそもそも結果を出力しましたか?
- 合格した場合、それはクリーンに合格しましたか?
- 失敗した場合、その責任はどこにありますか:テストハーネス、環境、それともアプリケーションですか?
バグ報告となるのは、たった1つの答えだけです。それは、アプリケーションに起因する失敗です。それ以外のすべての答えは別の何かに関する情報であり、それを的確に示す名前が付けられます。
テストが全く判定されないのはどのような場合ですか?
14の判定に含まれない状態が3つあります。これらはアプリケーションについて何も語らないためです:SKIPPED(テストが実行されなかった)、INTERRUPTED(Ctrl+C、--max-failuresによる中断、またはグローバルタイムアウトによって停止された)、およびCONFIG_ERROR(テストハーネスが起動できなかった)。これらはいずれもエビデンスフォルダやHistory行を作成しません。
INTERRUPTEDが存在するのには具体的な理由があります。これがないと、停止されたテストがパスのブランチに流れ込み、SECUREとして記録されてしまっていました。つまり、完了していないテストに対して緑の判定が下されていたのです。
合格(pass)はどのように評価されますか?
- SECURE:初回試行で合格し、修復は行われませんでした。
- AUTO_RECOVER:合格しましたが、自己修復機能によってこのテスト内のセレクターを置き換える必要がありました。作成者が記述したロケーターは機能しなくなっており、ページへの次の変更でスイートが完全に壊れる可能性があるため、修復された合格がクリーンとして報告されることはありません。元のセレクターを修正してください。
- FLAKY:一度失敗した後に再試行で合格し、修復は行われませんでした。アプリケーションまたはテストのいずれかで何かが不安定であり、何も修正されていません。
1つの例外:最初の試行がタイムアウトによってのみ失敗し、再試行で合格した場合、判定はSECUREになります。その合格は不安定さではなく、レイテンシーを示しています。
失敗にはどのように判定(バーディクト)が割り当てられますか?
テストが失敗すると、エンジンはその実行のエラーメッセージとネットワークログを読み取り、決められた順序でパターングループと照合します。最初に一致したグループによって判定が決定されるため、この順序自体が設計の一部となっています。
- まずはCONFIG_ERRORです。
Cannot find module、ReferenceError、SyntaxError、環境変数の不足、セットアップで失敗したフィクスチャなどが該当します。ハーネスが起動すらしていない場合、その後に発生する症状はすべてその結果にすぎません。パターンは意図的に狭く絞り込まれており、テストコードやその環境だけが引き起こし得るエラーに限定されています。CONFIG_ERRORが多すぎると、アプリケーションの実際のバグをハーネスのせいにしてしまう恐れがあるためです。 - CRASHED:
Target closed、Page crashed、DevToolsプロトコルエラー、SessionNotCreatedError、無効なセッションIDなどが該当します。ブラウザまたはドライバーが停止しました。これはインフラの問題ですので、マシンとドライバーをご確認ください。 - BLOCKED: エラーまたはネットワークログ内の403や429、CAPTCHA、アクセス拒否ページ、あるいはエンジンが画面上で検知したBotチャレンジなどが該当します。サイトが自身を防衛したため、リクエストはお客様のプロダクトに一切到達しませんでした。
- UNREACHABLE: ページが検知される前にネットワーク側で拒否されました。名前解決の失敗(Chromiumの
net::ERR_NAME_NOT_RESOLVED、FirefoxのNS_ERROR_UNKNOWN_HOST、WebKitのCould not resolve hostname)、接続の拒否、あるいはマシンがオフラインだったことなどが挙げられます。証明書エラーはここには含まれません。そちらは検出事項(finding)となります。 - TIMEOUT: Playwrightの
Timeout 30000ms exceeded、SeleniumのWait timed out after、TimeoutError、またはPlaywrightがタイムアウトとしてマークしたテストが該当します。制限時間を超過したナビゲーションはUNREACHABLEではなくTIMEOUTです。処理は開始されており、ページの応答が遅かったことを意味します。 - BREACHED_FLAKY: 上記のいずれにも当てはまらず、テストがすでに再試行されていた場合です。テストは失敗しており、その失敗自体にも一貫性がありません。バグを報告する前に、各試行内容を比較してください。
- BREACHED: 1回の試行において、上記のいずれにも当てはまらない場合です。アサーションが失敗し、環境やハーネスのパターンではそのエラーを説明できません。これがバグレポートとなります。
各グループは、PlaywrightとSelenium WebDriverの両方の文言をカバーしています。Seleniumのパターンが存在する前は、WebDriverのTimeoutErrorや古いchromedriverのSessionNotCreatedErrorは、あたかもアプリケーションに不具合があるかのように、どちらもBREACHEDとして報告されていました。
スリープ状態になったりロックされたりして実行を受け付けられない実機のAndroidスマートフォンも、BLOCKEDとなります。これはプロダクトの不具合ではなく、前提条件が満たされていない状態です。このルールは実際の事例から生まれました。キャンペーンの途中でスマートフォンがスリープ状態になり、4回連続で合格していたログインテストが致命的なレッド(不合格)として判定されてしまったのです。
カオス実行はどのように判定されますか?
実行時にChaos Labからのフォールトが注入されると、判定は「アプリケーションは耐え抜いたか?」という別の問いに答えるものになります。パス(SECUREまたはAUTO_RECOVER)はCHAOS_RESILIENTになります。FLAKYなパスやTIMEOUTを含め、それ以外はすべてCHAOS_BREACHEDとなります。注入されたフォールト環境下では、それらこそが影響そのものだからです。SKIPPED、INTERRUPTED、CONFIG_ERRORはそのまま維持されます。実行されなかったテストは回復性について何も示せないためです。
どの厳格なチェックによって成功(パス)が変更される可能性がありますか?
アサーションと並行して、セキュリティヘッダー、axe-coreによるアクセシビリティ、Web Vitalsや遅延読み込みのパフォーマンスバジェットという3つのチェックが実行されます。これらは実行ごとに検出内容を記録します。「設定」で厳格(strict)にした場合にのみ、判定を変更します。既存のアプリケーションでは、これらのいずれかを初日に厳格にするとテストスイート全体がレッドになってしまう可能性があり、常にレッドのテストスイートは誰にも読まれなくなってしまいます。
厳格に設定されている場合、これらはパスしたテストにのみ次の順序で適用されます: SECURITY_VIOLATION、A11Y_VIOLATION、PERFORMANCE_DEGRADED。3つの中でセキュリティが最優先されるのは、苦情ではなくインシデントに発展する可能性があるためです。失敗したテストがエスカレーションされることはありません。BREACHEDはすでにそれ以上に深刻な事象を示しており、その上に注意喚起を重ねると検出事項が埋もれてしまうためです。
CIには何が表示されますか?
7つのパス判定は終了コード0で終了します: SECURE、AUTO_RECOVER、FLAKY、CHAOS_RESILIENT、PERFORMANCE_DEGRADED、A11Y_VIOLATION、SECURITY_VIOLATIONです。保留事項はビルドの失敗としてではなく、レポートおよび「履歴」に表示されます。他の7つの判定は終了コード1となります。pytestおよびSeleniumのランナーは、Pythonが存在しない場合やエンジンに対応するドライバーがないブラウザの場合など、実行をまったく開始できなかった場合に終了コード2で終了します。
この手法の限界は何ですか?
- 分類はエラーテキストを読み取ります。ご自身で作成したメッセージに
403、Forbidden、またはAccess Deniedが含まれている場合はBLOCKEDとして読み取られ、is not a functionが含まれているエラーはCONFIG_ERRORとして読み取られます。カスタムアサーションメッセージは具体的に記述し、判定結果が想定と異なる場合はmetadata.jsonをご確認ください。 - TIMEOUT はアプリケーションが正常に動作していることの証明ではありません。その実行では判断できないことを示しています。毎回タイムアウトするテストは、確認してみる価値があります。
- リトライこそが FLAKY と SECURE、そして BREACHED_FLAKY と BREACHED を分けるものです。リトライを無効にすると、断続的な失敗は BREACHED になります。
- API テストには、別のルールによって決定される独自の 7 つの判定があります。API tests をご覧ください。
実際の失敗に関する判定はどこで確認できますか?
Evidence ページ では、ある失敗したテストを追跡し、各判定によってディスクに残されるすべてのファイル(report.md、metadata.json、raw-data.json、スクリーンショット、および実際の失敗の場合はビデオ)を一覧表示しています。30-day trial では、ご自身のテストで同じエンジンを実行できます。