モダンなWebアプリケーションのE2Eテストは、以前よりもかなり難しくなっています。
単にページを開き、ボタンをクリックし、。現在のアプリケーションには、Feature Flag、Shadow DOM、ReactのHydration、OAuth、MFA、複数タブ、複数テナント、地域別設定、AIエージェント、マルチモーダル入力など、テストを不安定にする要素が数多く存在します。
しかも厄介なのは、テストが失敗する場合だけではありません。
間違った理由でテストが成功することもあります。
この記事では、現在のWebアプリとAI機能をテストする際に見落としやすいポイントを、環境、フロントエンド、認証、SaaS、AIの5つの観点から整理します。
1. 「ローカルでは通るのにStagingだけ落ちる」を分解する
Stagingだけで失敗するテストは、単純なFlaky Testとは限りません。
Feature Flagによって実行時のUIが変わると、同じURLでも実際には別の画面構造が表示されます。ボタンがメニュー内へ移動したり、フォームが複数ステップになったり、特定ユーザーだけ新しいコンポーネントを受け取ったりします。
この問題を調べる際は、Feature FlagによるRuntime UIの差分でStagingだけブラウザテストが失敗する理由が参考になります。
テスト結果には、環境名だけでなく以下も残すべきです。
- 有効だったFeature Flag
- 対象ユーザーやテナント
- デプロイされたCommit ID
- 使用したSeed Data
- APIや依存サービスのバージョン
Preview Environmentも同様です。URLが起動しているだけでは、テスト可能な環境とは言えません。Ephemeral Preview Environment、Seed Data、環境差分を含むテスト計画のように、実行前に環境そのものを検証するフェーズが必要です。
例えば、メインのE2Eテストを開始する前に次を確認します。
- 正しいBuildがデプロイされている
- Seed Dataが投入されている
- QueueやEmail Serviceが動作している
- 必要なFeature Flagが有効である
- テストユーザーに正しい権限がある
これだけで、環境不備による大量の偽の失敗を減らせます。
2. API Mockが「偽の成功」を作ることがある
API Mockは便利ですが、実APIとの契約がズレると危険です。
本番APIではレスポンス構造が変更されているのに、Mockだけが古い形式を返している場合、テストは古い世界を検証し続けます。その結果、テストは安定しているのに、本番では機能しないという状態が発生します。
この現象は、API Mock Driftによってブラウザテストが間違った理由で成功する問題で詳しく解説されています。
対策としては、次のような方法があります。
- Mock ResponseをSchema Validationする
- OpenAPIやJSON SchemaからFixtureを生成する
- 一部のテストは実サービスに接続する
- 実レスポンスとFixtureを定期比較する
- 廃止済みフィールドを使うMockをCIで失敗させる
Mockを減らすことが目的ではありません。Mockが「存在しないBackend」を作らないようにすることが重要です。
3. React、Hydration、Shadow DOMでは「見える」と「操作可能」が違う
現代のフロントエンドでは、Elementが表示されていても、まだ操作可能とは限りません。
Server-Side RenderingされたHTMLが先に表示され、その後Client側でHydrationされる場合、ボタンは見えていてもEvent Handlerがまだ接続されていないことがあります。
Hydration mismatch、Client-side re-render、Server/Client UI driftのテスト方法では、この問題を実践的に整理しています。
React 19への移行後に隠れていたTiming Bugが表面化するケースもあります。React 19がブラウザテストのTiming問題を露出させる理由も確認しておくとよいでしょう。
固定Sleepではなく、アプリケーション固有の状態を待つべきです。
悪い例:
2秒待つ
良い例:
保存済みステータスが表示されるまで待つ
対象ボタンが有効になり、再描画されなくなるまで待つ
Hydration完了を示す状態を待つ
Shadow DOMやPortalもElement探索を難しくします。Shadow DOMとPortaled Modalを壊れにくくテストする方法で紹介されているように、Nodeの存在だけでなく次を確認する必要があります。
- 実際にクリック可能か
- Overlayに隠れていないか
- Keyboard Focusが正しく移動するか
- Escapeで閉じられるか
- 閉じた後に元のElementへFocusが戻るか
4. Skeleton、Sticky UI、Scroll SnapはDOM Assertionだけでは不十分
Progressive Loadingを採用したUIには、LoadingとLoadedの間に複数の状態があります。
- Skeleton
- Partial Content
- Background Refresh
- Empty State
- Retry State
- Stale Data
- Infinite Scroll中の追加Loading
Skeleton Screen、Progressive Loading、Empty Stateを正しくテストする方法のように、それぞれを別状態としてテストする必要があります。
また、CSS Scroll Snap、Sticky Header、Scroll-linked Animationなどは、DOM上でElementが存在していても、ユーザーからは操作できない場合があります。
CSS Scroll Snap、Sticky Section、Scroll-linked UIをMobile Bugまで含めてテストする方法では、Viewportと座標の確認が重要だと説明されています。
確認すべき例は以下です。
- Sticky HeaderがCTAを隠していないか
- Scroll Snap後に正しいCardが中央へ来ているか
- Mobile BrowserのAddress Bar変化後もLayoutが正しいか
- Orientation変更後もScroll位置が壊れないか
Visual Regressionも同様です。CSS Grid、Flexbox、Container Queryでは、小さな差分が大きなScreenshot Diffを生むことがあります。CSS Grid、Flexbox、Container QueryにおけるVisual Regression NoiseのBenchmark方法を参考に、False Positive率を測ることが重要です。
5. Cypressを安定させるのはToolではなく待機設計
CypressにはRetry機構がありますが、それだけでFlaky Testが消えるわけではありません。
再描画直前のElementを取得したり、force: trueで本当のUI問題を隠したり、Network Request完了を最終状態と誤認したりすれば、テストは不安定になります。
Cypress Testを安定させるための実践ガイドでも、安定性はSelectorよりも状態設計に左右されることが強調されています。
重要なのは、次のような習慣です。
- Arbitrary Waitを避ける
- UI上の意味ある状態を待つ
- Test Dataを明示的に作る
- 1つのTestに責務を詰め込みすぎない
- Detached ElementをRunnerの問題だけでなく再描画のサインとして扱う
6. SaaSでは「ログイン成功」より、その後のHandoffが壊れやすい
OAuth、MFA、Popup、Cross-tab Loginは、典型的な壊れやすいFlowです。
ユーザーはアプリからIdentity Providerへ移動し、MFAを完了し、Callback URLへ戻り、元のTabへSessionを反映させます。
OAuth Popup、MFA Prompt、Cross-tab Login HandoffをEndtestでテストする方法では、複数WindowやSession引き継ぎを含むテストの難しさが整理されています。
また、外部QA Partnerを利用する場合でも、単一ページのHappy Pathだけでは評価できません。Multi-window、Popup Authentication、Cross-domain Session Handoffを扱えるQA Partnerの選び方のように、実際の認証構成に近い環境で検証する必要があります。
7. Multi-tenant SaaSは「見えること」だけでなく「見えないこと」をテストする
Multi-tenant Applicationでは、自分のTenant Dataが見えることだけでは不十分です。
他TenantのDataが見えないことも証明する必要があります。
Multi-tenant App TestingとTenant IsolationでQA Platformに必要な機能を参考に、少なくとも2つのTenantを用意し、以下を確認します。
- Direct URLで別TenantのRecordへアクセスできない
- Search Resultに別Tenant Dataが出ない
- Exportに他Tenant Dataが混ざらない
- Recently Viewedに別Tenantの情報が残らない
- 別TabでTenantを切り替えてもSessionが混線しない
UIからLinkを隠すだけではIsolationとは言えません。Backend側のAuthorizationも含めて検証する必要があります。
8. Sign-up、Email Verification、Account Recoveryは分散システムとして扱う
Sign-up Flowは、Web Formだけではありません。
- Identity Service
- Email Provider
- Background Job
- Billing
- Fraud Check
- Tenant Provisioning
など複数のSystemが関係します。
Multi-step Sign-up、Email Verification、Account RecoveryをテストできるBrowser Testing Platformの評価方法では、以下のようなEdge Caseが重要です。
- Expired Verification Link
- Linkの二重使用
- 別Browser SessionでのVerification
- Email遅延
- Sign-upは成功したがBrowserがTimeout
- Social Login UserのPassword Recovery
- Invitation先Tenantの変更
Verification TokenをHard-codeすると、重要なHandoffをテストしていないことになります。実際のEmailを取得して、そこからLinkやOTPを使う方が現実的です。
9. Region、Locale、Time Zoneは静かに不具合を作る
Multi-region SaaSでは、同じ機能でもRegionによって挙動が変わります。
- Date Format
- Currency
- Data Residency
- Regional API
- Consent
- Daylight Saving Time
- Feature Availability
Multi-region SaaS、Locale Drift、Time-zone Sensitive Flowのテスト方法のように、境界値を意識したテストが必要です。
例えば、
- 深夜0時前後のSubscription Expiration
- DST切り替え日のReport
- Locale変更前後のDate入力
- Region Migration後のTenant
- UTC WorkerとLocal Browserの時差
などは、通常のHappy Pathでは見つけにくい問題です。
10. AI UIはOutputの内容だけでなく、周辺操作をテストする
AI機能のテストでは、生成された文章だけを確認しがちです。
しかし、実際には次のようなUIも重要です。
- Regenerate
- Retry
- Stop Generation
- Copy to Clipboard
- Edit Prompt
- Model Switch
- Continue Response
AI Output UIのRegenerate、Retry、Copy操作におけるEndtestとPlaywrightの比較では、生成内容が可変でもUI自体は決定的にテストできることが示されています。
例えば、次を確認できます。
- Regenerateが正しいMessageに紐づく
- RetryでUser Messageが重複しない
- Stop後もConversationが復旧可能
- Copy対象がStreaming途中の断片ではない
- 新しいMessage追加後も操作対象がずれない
出力全文の完全一致ではなく、構造、必須情報、禁止内容、UI Stateを検証する方が現実的です。
11. AIアプリのUI変更が多い場合、Assertionを分類する
AI ProductはUIやCopyが頻繁に変わります。
すべてをExact MatchにするとMaintenance Costが増えます。一方で、すべてを曖昧にすると重大なRegressionを見逃します。
UIとCopyが頻繁に変わるAIアプリにおけるEndtestとAutifyの比較を参考に、Assertionを次の2種類へ分けると管理しやすくなります。
固定すべき契約
- Promptが1回だけ送信される
- Responseが正しいConversationに属する
- Tool Call前に必要な確認が入る
- Stop Generationが機能する
- User Dataが別Sessionへ漏れない
柔軟に扱える表現
- Helper Text
- Minor Label
- Markdown Formatting
- Responseの言い回し
- 重要でないLayout差分
Security WarningやPermission表示などは、Copy変更が重大な意味を持つため、Exact Assertionが必要な場合もあります。
12. Prompt InjectionはChat Inputだけで起きるわけではない
Prompt Injection Testを、入力欄へ「以前の指示を無視して」と入力するだけで終わらせてはいけません。
Browser Agentは、Webpage、Email、PDF、Knowledge Base、Hidden DOM、Tool Responseなどから不正な指示を受け取る可能性があります。
AI-powered Browser WorkflowにおけるPrompt Injection Defenseのテスト方法では、外部Contentを「命令」ではなく「Data」として扱えるかが重要になります。
確認すべき点は以下です。
- 禁止されたTool Callを試みなかったか
- SecretをIntermediate Stepで漏らしていないか
- 未承認Domainへ移動していないか
- Userの元の目的を維持したか
- Sensitive Action前に確認したか
最終回答が安全でも、途中で危険なActionを試みていた可能性があります。
13. AIテストではReplay可能な証拠が必要
AIの失敗は再現しづらいため、Pass/Failだけでは十分ではありません。
必要な証拠には次が含まれます。
- Conversation全体
- System Instruction
- Retrieved Content
- Model名と設定
- Tool Call
- Tool Result
- Browser State
- Final Output
Prompt Injection Evidence、Conversation Replay、Unsafe Output Triageを扱うAI Testing Toolの評価方法では、Replay可能性が重要な評価軸として挙げられています。
同じScenarioを複数回実行し、失敗率を見ることも必要です。10回中9回安全でも、1回危険な挙動をするなら、DeterministicなPassとは扱えません。
14. Agentic Workflowは最終回答ではなくTool Call単位で検証する
AI Agentが正しい結果を返しても、その過程が安全とは限りません。
例えばCalendar Agentが正しいMeetingを作成したとしても、
- 一度Wrong PersonをInviteした
- Duplicate Eventを作成した
- PermissionのないCalendarを読んだ
- Conflictを無視した
可能性があります。
Agentic Workflow、Tool Call、Multi-step RecoveryをテストするAI Platformの評価ポイントでは、各Tool Boundaryを検証する必要があります。
- 正しいToolを選んだか
- Argumentは正しいか
- 権限は適切か
- Resultを正しく解釈したか
- RetryでSide Effectを重複させなかったか
- 必要なConfirmationを取ったか
Timeout、Partial Result、Rate Limit、Permission Denialなども意図的に注入すると、Recovery Pathの品質が見えます。
15. Multimodal AIでは入力同士の関連性を検証する
Text、Image、Audio、Screen Stateを同時に扱うAI Applicationでは、各入力が正しくても、それらの紐づけが間違っている場合があります。
Text、Image、Audio、Screen Stateを一緒に検証するMultimodal App向けAI Testing Market Reportでは、複数Modalities間の整合性が重要とされています。
例えば、
- Screenshotが別UserのSessionに紐づく
- AudioとScreenが時間的にずれる
- AIが古いFrameを参照する
- Image内のPrompt Injectionに従う
- 正しい情報を別Conversationから混ぜる
といった問題があります。
Timestamp、Session ID、Input IDを保存し、AIがどのInputを見たのか追跡できるようにする必要があります。
16. CI NoiseとProduct Regressionを分離する
Release直後にBrowser Testが複数失敗すると、すぐRollbackしたくなります。
しかし、Browser Worker、Network、Test Data、Session Startなどが原因の場合、Productは正常かもしれません。
Rollback前にProduct RegressionとCI Noiseを分ける方法では、証拠を分類することが推奨されています。
Product Regressionの可能性が高い証拠
- Manualでも再現する
- 複数Runnerで同じ失敗
- 新しいServer Errorがある
- 変更箇所と失敗箇所が一致する
CI Noiseの可能性が高い証拠
- Browser Session自体が開始していない
- 無関係なTestがSetupで失敗
- 別Workerでは成功
- Screenshotでは正しい状態
- NetworkまたはInfrastructure Error
Retryは便利ですが、最初の失敗を消さず、Retry前後の差分を保存するべきです。
17. MinificationとError Boundaryが原因を隠す
Developmentでは分かりやすいStack Traceが、Production BuildではMinificationによって読めなくなることがあります。
さらにError Boundaryが「Something went wrong」のようなGeneric UIへ置き換えると、Test Resultだけでは原因が分かりません。
Source Map、Minification、Error Boundaryが本当のStack Traceを隠す問題では、Production-like EnvironmentでもObservabilityを残す必要があると説明されています。
最低限、以下を保存すると調査しやすくなります。
- Build ID
- Browser Console
- Unhandled Exception
- Rejected Promise
- Source Map対応Stack Trace
- Request ID
- Active Feature Flag
Screenshotだけではなく、Application Logと結びつけることが重要です。
18. AIで巨大なFrameworkを作ってもMaintenanceは消えない
Claudeなどを使えば、Playwright Frameworkを短時間で大量生成できます。
しかし、初期実装が速くても、次の保守は残ります。
- Test Data
- OAuth Account
- MFA Secret
- Email Retrieval
- Tenant Provisioning
- Browser Upgrade
- CI Capacity
- Failure Triage
- Selector変更
- Cleanup
Claudeが巨大なPlaywright Frameworkを生成した後に発生するMaintenance Costでは、生成コストよりもOwnership Costが重要だと指摘されています。
AIはCodeを書く時間を減らせますが、どのWorkflowが重要か、どのFailureが本物か、どのTestを削除すべきかまでは自動で決めてくれません。
まとめ:2026年のE2Eテストで見るべきもの
現在のE2Eテストでは、Selectorだけを改善しても十分ではありません。
見るべき対象は次の通りです。
-
Environment
- Build、Feature Flag、Seed Data、Region
-
Frontend State
- Hydration、Re-render、Progressive Loading
-
Geometry
- Sticky UI、Scroll、Viewport、Overlay
-
Identity
- OAuth、MFA、Cross-tab、Email Verification
-
SaaS Boundary
- Tenant、Locale、Time Zone、Data Isolation
-
AI Behavior
- Prompt Injection、Tool Call、Replay、Multimodal Input
-
Evidence
- Screenshot、Video、Console、Network、Build ID、Conversation
安定したテストとは、単に「落ちないテスト」ではありません。
なぜ成功したのか、なぜ失敗したのかを説明できるテストです。
テスト結果に十分な証拠があれば、Flaky Testを隠すためにRetryを増やす必要も、原因不明の失敗でReleaseを止める必要も減っていきます。
モダンなWebアプリとAI機能をテストするうえで最も重要なのは、Test Runnerを選ぶことだけではありません。
どの状態を観測し、どの境界を検証し、どの証拠を残すかを最初に設計することです。
