Upgrade to Pro — share decks privately, control downloads, hide ads and more …

E2Eってつらくないですか?E2Eの管理コストを下げる手段とその実践

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

 E2Eってつらくないですか?E2Eの管理コストを下げる手段とその実践

Avatar for Kosei Akaboshi (akaboshinit)

Kosei Akaboshi (akaboshinit)

October 29, 2026

More Decks by Kosei Akaboshi (akaboshinit)

Other Decks in Technology

Transcript

  1. 例えば残高のチャージは 4 つの画面をまたぐ 01 連続的なユーザー操作を テストできるのが E2E ログインする アプリを開いてログイン 02

    03 04 チャージ画面で金額を選ぶ 決済画面で支払いを完了 マイページで残高が増えたか 見る 金額を選ぶ 支払う 残高を見る 07
  2. E2E で確かめるのはユーザーの一連の動作が問題ないか チャージ 金額を選ぶ 画面 1 → 決済 支払う 画面

    2 → マイページ 残高が 増えている 画面 3 前の画面の結果が 次の画面に正しく 引き継がれるかまで確かめる 複数の操作からなる1 本のテストをシナリオと呼ぶ 08
  3. E2E では連続した操作でしか起きないバグを検知できる 画面ごとに見ると問題ないのに 続けて操作すると壊れる チャージ → マイページへ戻る → 残高が古いまま ログアウト

    → ほかの画面へ移動 → ログイン中の表示のまま フォームに入力 → 別の画面へ → 戻る → 入力した内容が消えている 09
  4. テストの書き方 チャージすると残高が増える', ($) async { patrolTest(' await $.pumpWidgetAndSettle(App()); // ログイン

    await $(#email).enterText('test@…'); ログイン').tap(); await $('チャージ').waitUntilVisible(); // 画面遷移を確認 await $(' 金額を選んで支払う await $('1,000円').tap(); await $('お支払い').waitUntilVisible(); // 画面遷移を確認 await $('支払う').tap(); // 残高を確認 await $('マイページ').tap(); await $('残高 1,000円').waitUntilVisible(); ••• 9:41 チャージ チャージ金額を選択 500円 1,000円 選択中 ••• 9:41 お支払い チャージ金額 1,000円 支払い方法 クレジットカード 残高 3,000円 1,000円 5,000円 次へ // 01 ••• 9:41 マイページ 金額を選ぶ 支払う 02 支払う 03 残高を見る }); 10
  5. 採用事例 会社 対象 出典 Google 全社 Google Testing Blog「Just Say

    No to More End-to-End Tests」2015 ほか Google Flutter Firebase ドキュメント「Flutter との統合テスト」 メルカリ PayPayカード Android 「E2E テストのテスト結果を可視化することで気づきが生まれた」2019 Web LINEヤフー Tech Blog「大規模スクラム×E2E 自動テストへの挑戦で見えてきたこと」2025 ZOZO Web ZOZO TECH BLOG「Autify を導入して E2E 自動テストを最適化した話」 WINTICKET Flutter FlutterKaigi 2023「Flutter アプリにおけるテスト戦略の見直しと自動テストの導入」 11
  6. E2E という夢 E2E があれば 手間なしで安心してリリースできる! 毎朝全シナリオが自動で PASS ✓ リリース前の手動確認はいらない ✓

    障害はリリース前に全部見つかる ✓ ログイン 会員登録 購入 検索 ✓ PASS ✓ PASS ✓ PASS ✓ PASS 12
  7. flaky:E2E が避けられない問題 “a test that exhibits both a passing and

    a failing result with the same code.” Google Testing Blog「Flaky Tests at Google and How We Mitigate Them」2016 同じコードなのに 成功したり失敗したりするテスト E2E のつらさ 15
  8. flaky テストの例 同じテストを 5 回実行すると #1 main a1b2c3d ✓ PASS

    #2 main a1b2c3d ✕ FAIL #3 main a1b2c3d ✓ PASS #4 main a1b2c3d ✓ PASS #5 main a1b2c3d ✕ FAIL コードもテストも何も変えていない なのに 結果だけが変わる E2E のつらさ 16
  9. Google でも flaky は日常 16% 全テストのうち ときどき結果が変わるテスト 84% 「急に落ちた」ケースのうち 原因が

    flaky だったもの 出典: Google Testing Blog「Flaky Tests at Google and How We Mitigate Them」(John Micco, 2016) E2E のつらさ 17
  10. flaky の原因 ② アプリの外で落ちる アプリは正しく動いているのに 外の都合で落ちる アプリの外で起きたこと テストデータ 外部サービス アカウント

    実行環境 dev サーバーのデータが書き換わって前提が崩れた 何度もテストを流して SMS 認証の送信回数の上限に 達した 別のテストが同じアカウントで同時にログインした 手元では通るのにデバイスファームでだけ落ちる テストは → ✕ 期待した画面にならず失敗 → ✕ ログインできず失敗 → ✕ 操作が競合して失敗 → ✕ 手元で再現できない E2E のつらさ 20
  11. E2E のつらさ: テストコードの運用 施策や正常な変更で UI が変わると テストが操作したいボタンを見つけられなくなる 9:41 レース詳細 •••

    9:41 レース詳細 変更前 $('投票する').tap() 画面:「投票する」 文言を変えた後 $('投票する').tap() 画面:「今すぐ投票」 ✓ 見つかる 投票する ••• ✕ 見つからない 今すぐ投票 E2E のつらさ 21
  12. 現実: E2E の運用はつらい 何も変えていないのに落ちる 落ちるたびに原因の調査が始まる 正常な変更でもテストが落ちる 同じコードでも日によって PASS したり FAIL

    したりする アプリか、環境か、テストか。録画とログを行ったり来たり 画面の文言やレイアウトが変わるだけで落ちる 24
  13. 失敗調査の歴史 - E2E 導入当初 テストが落ちたら膨大な情報を確認 1 2 3 Test Lab

    テスト 結果 ✕ e2e_test_android Pixel 6 · API 33 ✓ e2e_test_android Pixel 7 · API 34 ✕ e2e_test_android Galaxy S21 · API 31 ✓ e2e_test_android Pixel 5 · API 30 ✓ e2e_test_android Pixel 8 · API 34 失敗 成功 失敗 成功 成功 Test Lab のコンソールを開く どのテストが落ちたかを探す 07:01:12.100 I ActivityManager: Start proc com.example.app 07:01:13.137 D Flutter: [patrol] start: 07:01:14.174 D Flutter: [patrol] tap: 07:01:15.211 I art: Background concurrent GC freed 12MB チャージすると残高が増える マイページ 07:01:16.248 D Flutter: [patrol] tap: チャージ 07:01:17.285 W System.err: java.net.SocketTimeoutException 07:01:18.322 I chromium: [INFO:CONSOLE(1)] page loaded 07:01:19.359 D Flutter: [patrol] enterText: 1000 07:01:20.396 W InputMethodManager: startInputInner failed 07:01:21.433 D Flutter: [patrol] tap: 07:01:22.470 I art: Background concurrent GC freed 8MB 07:01:23.507 D Flutter: [patrol] waitUntilVisible: 07:01:24.544 E Flutter: TestFailure: Expected: exactly one matching can 07:01:25.581 E Flutter: Actual: _TextWidgetFinder: 07:01:26.618 I ActivityManager: Process com.example.app has died チャージする 残高 01:42 / 03:10 テストの録画映像を見る どの画面で止まったかを探す 07:01:27.655 D Flutter: [patrol] finish 膨大な量の端末ログを読む エラーの手がかりを探す WINTICKET で E2E を運用してきて 31
  14. そのためにやったこと AI に失敗調査を任せるための 4 つのカイゼン カイゼン 1 カイゼン 2 カイゼン

    3 カイゼン 4 テストコードを改善して落ちにくくする Patrol で高速に直せる 一目でテストの情報を確認できる証拠を自動で残す テスト失敗トリアージ Skill 38
  15. 04 カイゼン 1: テストコードを改善して落ちにくくする カイゼン 1 カイゼン 2 カイゼン 3

    カイゼン 4 テストコードを改善して落ちにくくする Patrol で高速に直せる 一目でテストの情報を確認できる証拠を自動で残す テスト失敗トリアージ Skill カイゼン 1: テストコードを改善して落ちにくくする 39
  16. 実例 ①: コードは悪くないのに落ちる 例 課題 対応 別のシナリオが残高や設定を書き換えていて テストが想定と違う状態から始まる 複数のシナリオが同じアカウントを使うと アカウントの状態が競合する

    全シナリオにそれぞれ別のユーザーを用意して アカウントの競合が起きないようにした カイゼン 1: テストコードを改善して落ちにくくする 41
  17. それでも落ちる カイゼン 1 カイゼン 2 カイゼン 3 カイゼン 4 テストコードを改善して落ちにくくする

    Patrol で高速に直せる 一目でテストの情報を確認できる証拠を自動で残す テスト失敗トリアージ Skill カイゼン 1: テストコードを改善して落ちにくくする 44
  18. 05 カイゼン 2: Patrol で高速に直せる カイゼン 1 カイゼン 2 カイゼン

    3 カイゼン 4 テストコードを改善して落ちにくくする Patrol で高速に直せる 一目でテストの情報を確認できる証拠を自動で残す テスト失敗トリアージ Skill カイゼン 2: Patrol 45
  19. Patrol にテスト基盤を変更 E2E のテスト基盤を integration_test から Patrol に変更 Patrol は

    LeanCode が開発する Flutter 向けの E2E フレームワーク。 integration_test の上に作られている カイゼン 2: Patrol 46
  20. Patrol の決め手は patrol develop patrol develop hot reload で 直したテストをその場で何度も回せる

    1 2 3 ビルドは最初の 1 回だけ アプリを起動したままテストコードを書き換える ターミナルで R を押すと数秒で流し直せる カイゼン 2: Patrol 48
  21. AI 向けの機能: Patrol MCP 人が速く直すための道具を AI もそのまま使える AI が使えるツール run

    status screenshot native-tree quit テストを走らせて終わるまで待つ 実行の状態と直近のログを見る いまの端末の画面を撮る OS の画面も含めた UI ツリーを読む セッションを終わらせる カイゼン 2: Patrol 51
  22. 06 カイゼン 3: 一目でテストの情報を確認できる証拠を自動で残す カイゼン 1 カイゼン 2 カイゼン 3

    カイゼン 4 テストコードを改善して落ちにくくする Patrol で高速に直せる 一目でテストの情報を確認できる証拠を自動で残す テスト失敗トリアージ Skill カイゼン 3: 一目でテストの情報を確認できる証拠を自動で残す 52
  23. 人が調べていた頃の調査 落ちてから人が証拠を探しに行っていた それだけでは落ちた原因を見分けられない 頼りになるのはこの 2 つだけ エラーメッセージ と 動画 flaky?

    たまたま落ちただけ 実行環境? 端末・ネットワーク・デバイスファーム コード? アプリかテストのバグ → どれなのか判断に時間がかかる カイゼン 3: 一目でテストの情報を確認できる証拠を自動で残す 53
  24. 参考にした記事 Very Good Ventures / 2025-09 Elevating Flutter Test Reports

    with Allure https://verygood.ventures/blog/elevating-flutter-testreports-with-allure/ カイゼン 3: 一目でテストの情報を確認できる証拠を自動で残す 55
  25. 記事の概要 E2E の細かいステータスを レポート形式で出力する → 落ちたときにどこで何が起きたかをすぐ突き止められる 課題 Flutter の E2E

    のレポートは読みにくいログになりがち やったこと ステップごとの結果を書き出してレポートにまとめる仕組みを自作 テストの状況と証拠がひと目で分かる ポイント カイゼン 3: 一目でテストの情報を確認できる証拠を自動で残す 56
  26. 記事が推奨するレポート形式 OSS のテストレポートツール Allure Report テスト結果を見やすい HTML レポートにする 入力 出力

    対応 https://allurereport.org/ テスト結果の JSON(名前・状態・ステップ・添付) ステップや添付付きで見られる HTML レポート JUnit など Java 発祥。Python・JavaScript・Kotlin などにも対応 Flutter は公式対応なし → 記事では自作 カイゼン 3: 一目でテストの情報を確認できる証拠を自動で残す 57
  27. レポートの課題 E2E のレポートは端末の中に書かれる デバイスファームの端末 テストを実行 → report.json ✕ そのままでは取り出せない 端末の外(CI)

    人も AI もレポートを読めない テストコードはアプリと一緒にビルドされて端末の上で動くから。 テストが書いたファイルも CI ではなく端末に保存される カイゼン 3: 一目でテストの情報を確認できる証拠を自動で残す 59
  28. 設定 gcloud で実行するときにフラグを 1 つ足すだけ gcloud firebase test android run

    \ --type instrumentation \ --app app-debug.apk \ --test app-debug-androidTest.apk \ --directories-to-pull=/sdcard/allure-results カイゼン 3: 一目でテストの情報を確認できる証拠を自動で残す 61
  29. 何を残しているか 1 つのテストにつき この 5 つを残す name status statusDetails steps

    attachments どのシナリオか 結果 何が起きたか どの操作を行ったか エラー時の画面 シナリオ名 成功 broken 予期しないエラー passed 確認が失敗 skipped 実行されず failed message(エラー文)と trace 操作ごとの名前と結果 スクリーンショット カイゼン 3: 一目でテストの情報を確認できる証拠を自動で残す 62
  30. レポートの内容 読むだけでどこで・なぜ落ちたかが分かる レポート JSON(例) { ログインして投票できる", "name": " "status": "failed",

    "statusDetails": { 投票する' not found" }, "message": "Finder: ' "steps": [ アプリを起動する", "status": "passed" }, { "name": "投票ボタンを押す", "status": "failed" } ], { "name": " "attachments": [{ "type": "image/png" }] } ← どのシナリオか ← 結果 ← なぜ落ちたか ← どの操作で止まったか ← そのときの画面 カイゼン 3: 一目でテストの情報を確認できる証拠を自動で残す 63
  31. flaky になりやすい理由も残す どうしても flaky になりやすいテストは そのコンテキストをエラーメッセージに残す flaky になりやすい理由 レポートに残すエラーメッセージ(例) 開催の状況

    " 投票の締切 並行実行 テストアカウント 端末の回線 ライブ映像 投票ボタンが無効でした。12R の締切 14:32:00 まで残り 1 分 48 秒(2 分前から投票不可)。 別のレースで再実行してください" ログインに失敗しました(409 Conflict)。test-user-03 は別の実行でログイン中でした" " ライブ映像の再生が始まりませんでした。10 秒待っても buffering のまま(回線速度 1.2 Mbps) 。端末の通信状態を確認してください" " カイゼン 3: 一目でテストの情報を確認できる証拠を自動で残す 64
  32. 原因がすぐ分かる レポートを見れば flaky・実行環境・コードのどれで落ちたのかがすぐ分かる 原因 レポートのどこを見るか 例 次にやること flaky 残したコンテキスト 締切まで残り

    1 分 48 秒で 投票ボタンが無効だった → 再実行する 端末とファームの情報 端末の起動に失敗した デバイスファームが応答しない → 基盤を確認する ステップと画面 「投票ボタンを押す」で failed 画面にボタンがない → アプリを直す たまたま落ちた 実行環境 環境のせいで落ちた コード アプリが壊れた カイゼン 3: 一目でテストの情報を確認できる証拠を自動で残す 65
  33. 07 カイゼン 4: テスト失敗トリアージ Skill カイゼン 1 カイゼン 2 カイゼン

    3 カイゼン 4 テストコードを改善して落ちにくくする Patrol で高速に直せる 一目でテストの情報を確認できる証拠を自動で残す テスト失敗トリアージ Skill カイゼン 4: テスト失敗トリアージ Skill 66
  34. 分けずに直すとバグを隠してしまう テストを直したらバグごと消えた 1 2 3 4 アプリのバグで「投票する」ボタンが出なくなる E2E が落ちる 投票する'

    not found Finder: ' テストのせいだと思ってボタンを押す手順を消す テストは通る。バグはそのままリリース テストは成功するのにサービスは壊れる FAILED PASSED カイゼン 4: テスト失敗トリアージ Skill 67
  35. 直す前にまず分類する 失敗を再現可能な証拠へ結び付け 仕様やテストを安易に変更せず次のアクションを決める 判断のしかた 1 まずレポートを見てどこで・どんなエラーで落ちたかを確かめる 2 履歴を見て、いつから落ちているかを確かめる 3 その頃の

    app/server/web のプロダクションコードの変更を見る 4 同じ時間帯にほかのテストもまとめて落ちていないか 5 過去に同じエラーが出ていないか 6 テストコード側の変更(画面の文言・Key)がないか カイゼン 4: テスト失敗トリアージ Skill 68
  36. 原因を 4 つに分ける 調べた結果から原因を 4 つのどれかに決める test_bug production_bug infra_failure flaky

    テストコードの問題 アプリのバグ 実行環境の問題 たまたま落ちた カイゼン 4: テスト失敗トリアージ Skill 69
  37. 最終判断以外を AI に任せる Cognition Devin 自分の開発環境を持って動くAI のソフトウェアエンジニア タスクを渡すとコードを書いてテストを流し PR まで出す

    クラウド上の自分専用の環境 (シェル・エディタ・ブラウザ) 似ているもの Claude Code や Codex などのコーディングエージェント してくれること 動く場所 https://devin.ai/ja 最終判断以外を AI に任せる 73
  38. 最終判断以外を AI に任せる Devin は自分で Ubuntu・macOS を立ち上げられる 「必要に応じて、Windows・Mac・Linux の仮想マシンを自分で立ち上げ、ビルドやテストを行う」 Devin

    公式サイト 画像: https://x.com/ftnext/status/2115032465870078095 https://devin.ai/ja 画像: https://x.com/walden_yan/status/2099897237279289391 最終判断以外を AI に任せる 74
  39. Devin が実際にやっている 4 つの操作 起点 E2E の終了イベント 調べる 再現する 直す

    確かめる 人間 承認する Test Lab から GCS に出力されたレポートやスクショを取得してトリアージ Skill で分類を確定 01 させる 02 仮説をもとに Ubuntu・macOS 上のエミュレーター / シミュレーターでテストを実行する 03 確定した分類に沿って、最小かつ適切な差分で直す 04 最後に Test Lab の実機で E2E を流してその録画と結果を PR に添付する PR をアプルーブしてマージすれば直っている 最終判断以外を AI に任せる 76
  40. 参考文献 Patrol Patrol MCP https://patrol.leancode.co https://pub.dev/packages/patrol_mcp Sycophancy to Subterfuge (Anthropic,

    2024) ImpossibleBench (2025) https://arxiv.org/abs/2406.10162 https://arxiv.org/abs/2510.20270 EvilGenie (2025) Elevating Flutter Test Reports with Allure (Very Good Ventures) https://arxiv.org/abs/2511.21654 https://verygood.ventures/blog/elevating-flutter-test-reports-with-allure/ Just Say No to More End-to-End Tests (Google Testing Blog, 2015) Flaky Tests at Google and How We Mitigate Them (Google Testing Blog, 2016) https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html https://testing.googleblog.com/2016/05/flaky-tests-at-google-and-how-we.html Flutter との統合テスト (Firebase Test Lab) E2E テストのテスト結果を可視化することで気づきが生まれた (メルカリ, 2019) 大規模スクラム×E2E 自動テストへの挑戦で見えてきたこと (LINEヤフー, 2025) Autify を導入して E2E 自動テストを最適化した話 (ZOZO) https://firebase.google.com/docs/test-lab/flutter/integration-testing-withflutter https://techblog.lycorp.co.jp/ja/20250116a https://engineering.mercari.com/blog/entry/2019-02-12-080000/ https://techblog.zozo.com/entry/autify-introduction 行動とまとめ 79