エンドツーエンド(E2E)テストは、Android/iOS、画面サイズ、OSバージョンなど様々なプラットフォームで動作するネイティブアプリケーションにおいて特に重要です。E2Eテストは、この断片化された生態系全体で行動の違いを検出します。
しかし、E検査2E検査の信頼性を維持することは、そもそも試験を書くよりも難しいことが多いです。
断片化されたデバイスエコシステム、テストフレームワークのギャップ、ネットワークの不整合、不安定なテスト環境、そして絶えず変化するUIがテストの不安定さに寄与しています。チームはUIの変更や環境の不安定さによる失敗したテストを常に修正し続けるサイクルに陥りやすく、テストインフラ全体の信頼性を向上させることすらできません。彼らは最終的に、E2Eテストをワークフローに取り入れることにフラストレーションを感じ、ためらいがちです。
中規模企業でネイティブのE2Eテストインフラ構築を主導した経験から、長期的なテストの安定性を確保するために、テストの所有権、観測可能性、通知の戦略を定義し実装することがいかに重要かを痛感しました。この記事では、チームが直面している課題について議論し、信頼できるE2Eシステムを構築するための教訓を共有します。
リアクティブテスト保守の課題
CIに対して定期的なE2Eランを設定した後、チームは当初、失敗したテストのトリアージ、調査、修正に注力し、テストの安定性を向上させました。しかし、不安定なテストをほぼ1年にわたってパッチで修正しても、E2Eスイートの信頼性は改善せず、エンジニアたちはテストスイートの有用性と信頼性に対する信頼を徐々に失っていきました。
壊れたテストの修正に主に注力するチームは、不安定性の根本原因を解決せずに失敗を追いかける悪循環に陥りがちだと学びました。この受動的なアプローチはいくつかの問題を引き起こします:
- テストスイートの脆弱性:チームが基盤となるアプリの変更や不安定な環境の実際の問題に対処せずに壊れたテストをパッチ適用し続けると、テストスイートはますます脆弱になります。時間が経つにつれて、実際の製品欠陥とは無関係な理由でテストが失敗し、本物の回帰とノイズの区別が難しくなります。
- 高いメンテナンスコスト: 不安定なテストのデバッグや修正には、開発者の多くの時間とリソースがかかることが多いです。ユニットテストが高速で単独で失敗するのに対し、E2Eテストは開発、ステージング、またはプレプロダクション環境に対して実行されるため、失敗の再現や診断がより困難になります。異なる画面サイズやOSバージョンのデバイス間でE2Eテストを調整するには追加の作業が必要であり、修正は簡単な作業ではありません。
- テストスイートへの信頼を低下させる: 故障が頻発しノイズが大きいと、チームはEスイート2Eスイートへの信頼を失い、テスト失敗を無視しがちです。これはそもそも自動化テストの目的を損なっています。代わりに、チームはローカルの開発テストや手動のQAサイクルで変更の検証に頼っています。時間が経つにつれて、スイートは安全装置というよりは負担となり、納品を遅らせるだけでなく、むしろ促進します。
E2E検査を反応的に修正することで、放出サイクルが遅くなります。開発者は失敗したテストを繰り返し修正・再実行するために多くの時間を費やさなければならず、チームは実際の回帰を検出するために手動QAに頼っています。
信頼性の高いE2Eインフラの構築
テストスイートの安定性が1年以上失敗を追いかけても改善しなかったため、私たちは一歩引いて過去の結果を分析し、パターンを探しました。
多くの障害は不安定な環境やテストアカウントの予期せぬ状態に起因することが判明しました。例えば、テスト環境でのAPI遅延の急増は誤陰性を引き起こし、ノイズを増幅させました。同様に、既存のユーザーアカウントに対してテストを行う場合、過去の失敗や複数のテストが同じアカウントを使おうとした場合に不整合になることがあります。
テストインフラの改善に投資することが、安定し信頼できるネイティブE2Eテストワークフローを実現する唯一の方法だと学びました。これには、テスト環境の安定化、明確なテスト所有権の定義、ノイズの多いアラートの削減、観察可能性の向上が含まれます。これらをそれぞれ詳しく見ていきましょう。
試験環境の安定化
多くの不安定なE2Eテストは、機器の断続的な問題、ネットワークの不安定さ、ステージング環境でのAPIダウンなど、基盤環境の不整合に起因します。
ノイズが多く信頼性の低いテストを避けるために、以下のテスト実践を用いて安定し標準化されたテスト環境を確保してください。
- デバイスと環境の設定を標準化する: デバイスおよび試験環境の安定性問題は、試験の安定性に大きな影響を与えます。APIのダウンタイムを減らすために、不安定なビルドや実験機能による干渉を防ぐために、E2Eテスト環境を開発者やステージング環境から隔離してください。チームは、本番対応のアーティファクトを使った安定した事前本番環境を構築するか、E2E実行ごとに一時的な環境を立ち上げて一貫性を確保することができます。標準化されたデバイスイメージやコンテナ化されたエミュレーターで、OSのバージョン、設定、リソースが一貫した上でテストを行うことで、安定性がさらに向上します。重要なフローについては、物理デバイスファームで定期的に実行をスケジュールし、実際のハードウェアと照合して検証しつつ、日々のテストを安定かつコスト効率よく保つことができます。
- セッションごとのテストデータの分離: データに修正を加えるテストは、白紙の状態から始めるべきです。例えば、todoアプリケーションのテスト中は、予測不能なアカウント状態による予期せぬシナリオを避けるために、すべてのテストセッションごとに新しいテストアカウントを使うべきです。テストを高速化するために、『ビフォー』フックでセットアップスクリプトを実行してアカウント作成を処理し、必要なデータを自動でシードします。
- 特定のネットワークの反応を嘲笑する: E2Eテストは実際のデータを使ってユーザージャーニー全体をテストすることを目的としていますが、場合によっては予測可能なテスト環境を維持するために特定のAPI応答をモックする必要があることもあります。例えば、アプリケーションがA/Bテストに依存したり、機能フラグを使用している場合、異なるセッションはユーザー割り当てに応じて異なる体験を受けることがあります。これにより、実際の回帰とは無関係な予期せぬ故障が発生することがあります。テストビルドでこれらの応答をモックすることで、セッション間の一貫性を確保し、異なるユーザー体験を扱う複雑なテストケースの構築を避けられます。
明確なテスト所有権の確立
テストが失敗すると、誰が調査し修正する責任があるのかが不明瞭になることが多いです。時間が経つにつれて、明確なテスト所有権や責任の欠如が、信頼性を欠き、メンテナンスも行われず、不安定なテストを生み出します。
製品機能の所有権に基づいてテストの所有権を割り当てることで、この問題をある程度緩和できます。理想的には、所有チームが重要なフローのテストの作成、保守、修正を担当すべきです。この所有モデルにより、故障は迅速にトリアージされ、製品の進化に合わせてテストが更新され、古臭く不安定になることがありません。
複数のプロダクトチームが単一のユーザーフローの一部を所有するコードベースでは、テストの所有権が難しくなります。例えば、ショッピングアプリケーションでは、異なるチームがログイン、商品カタログ、レジ体験を所有している場合があります。ログインステップでチェックアウトフローテストが失敗すると、どのチームがトリアージすべきか混乱しやすくなります。明確な方針がなければ、失敗が無視されたり、複数のチームが重複作業を行ったりする可能性があります。
これらのシナリオに対応するために、エンドユーザー体験に基づいてテストごとに最初の接触点(POC)を定義するポリシーを設定します。これにより、単一のチームが問題のトリアージを担当しつつ、必要に応じて上流の依存関係に修正を委ねることができます。
ノイズを減らし、アラート機能を向上させる
ネイティブのE2Eテストでよくある課題は、不安定または失敗したテストによるノイズの多いアラートです。一時的なネットワークやデバイスの問題で不安定なテストが失敗すると、チームはしばしば実行に移らないアラートで溢れかえます。既知のバグに関する繰り返しの失敗通知もアラート疲労の原因となります。
以下の技術はこのノイズを軽減し、実行可能な故障時のみチームに通知を行います。
- 不安定なテストと既知のバグ: すべてのテスト失敗をチームに報告・通知する代わりに、不安定または既知の問題に関連するテストからのアラートをコード変更なしでミュート化できるようにしましょう。ミュートテストはリモート設定や環境変数、または BrowserStackのようなツールで管理できます。フォローアップのためにフラグを立て、アラートは新規または予期せぬ回帰のみに行わせてください。ミュートは特にE2Eテストで重要です。なぜなら、失敗したテストを修正するには開発者の時間とリソースが多大な必要があるからです。繰り返されるアラートは特に開発者にとって気が散ることがあります。
- 故障の詳細を通知に充実させる: 一般的な失敗メッセージの代わりに、失敗したユーザーフロー、コミット詳細、エラーメッセージ、ログやダッシュボードへのリンクなどの詳細をアラートに含めましょう。これらの詳細により、開発者は問題をより早く特定・トリアージし、より迅速な修正とスイートへの信頼度向上につながります。
- テストの指標や傾向を追跡する: テストスイートレベルのレポートに加え、テストの過去の結果を追跡・分析することで、失敗率、不安定さの傾向、故障ホットスポットを理解しましょう。例えば、ログインフローで繰り返し失敗が見られる場合、それは不安定なテストや散発的なバグの兆候かもしれません。これらの指標を時間をかけて追跡することで、Eスイート2Eスイートが改善しているか劣化しているかを可視化し、影響に基づいて安定化の優先順位をつけるのに役立ちます。
Docker化されたエミュレーターを用いたE2Eのスケーリングのハイブリッド戦略
ネイティブのE2E検査を大規模に実施することは、コストとリソースの制約から困難です。実際のクラウドベースのデバイスへのアクセスを提供するデバイスファームは、大量のテストを高頻度で実行するには高コストです。これは、変更がマージされる前のすべてのプルリクエストで実行されるCIパイプラインとE2テストを統合する制約となります。
前述の通り、Docker化されたエミュレーターをPRビルドに使うハイブリッドテストアプローチと、定期的な実行を行う実際のデバイスを使うことで、この課題を克服できます。私たちのチームがPRチェックをDocker化されたエミュレーターに移行したことで、より速いフィードバックが得られ、クラウドデバイスのコストを大幅に削減しました。
コンテナ化されたデバイスランナーはCIで迅速に立ち上げることができます。例えば、 docker-android イメージはコンテナ化されたDocker環境でAndroidエミュレーターを動かすことができます。複数のデバイスプロファイル、OSバージョン、AppiumやEspressoなどのUIテストフレームワークをサポートしています。チームはこれらのエミュレーターをCIパイプラインに簡単に統合し、大規模なテスト予算を投じることなくE2Eテストを大規模に実行できます
モバイルウェブ向けにE2Eテストを構築する場合、 コンテナ化されたブラウザイメージ を使って異なる環境で一貫してテストを実行することで、コストや設定の複雑さをさらに削減できます。
希望はある!
もしチームが私たちのようにネイティブのE2Eテストの失敗を追いかけてきたなら、テストの安定性を向上させることなく、エンジニアリングの時間とリソースを無駄にしている可能性が高いです。この記事が、テスト環境、デバイス設定、アラート、観察可能性の改善というより良い方法があることをあなたに励ましにしたことを願っています。
まずは過去のテスト失敗を分析し、それらをバケットに分類することが最善の第一歩です。これらの洞察を活かして、不安定さを減らすための実行可能な項目を定義しましょう。このロードマップを使って、最も効果をもたらすテストインフラ投資やプロセス変更を特定しましょう。
私たちのチームがテストインフラの改善に投資した後、安定性が明確に向上しました。開発者は実際の故障をよりよく理解できるようになり、ノイズの多い警告の数も減りました。不安定さは完全に消えませんでしたが、テストスイートの信頼性向上により、本番環境にリリースされる前に複数のネイティブアプリ回帰を発見することができました。
この記事があなたも同様の勝利を収める助けになれば幸いです。