E2Eテストを作成する際の考慮事項#frontend @ twiliosendgrid

公開: 2020-09-19

Twilio SendGridでは、新しい機能またはページ開発サイクルの終わりに向けてエンドツーエンド(E2E)テストを作成し、エンドユーザーの観点からすべてのパーツがフロントエンドとバックエンドの間で正しく接続および機能していることを確認します。

独自のカスタム社内RubySeleniumフレームワーク、WebdriverIO、主にCypressなどのさまざまなE2Eテストフレームワークとライブラリを2年以上実験してきました。これは、すべての移行を文書化したブログ投稿シリーズのパート1パート2で強調されています。ソリューション。 使用したフレームワークやライブラリに関係なく、自動化してE2Eテストを作成できる機能について同じ質問をすることになりました。 テストできる機能を特定した後、テストの作成と設定に同じ一般的な戦略を何度も適用していることに気付きました。

このブログ投稿では、特定のライブラリまたはフレームワークでE2Eテストを作成するための予備知識は必要ありませんが、Webアプリケーションを見て、ページが正しく機能するかどうかをテストするためにブラウザーで物事を自動化する方法について疑問がある場合に役立ちます。 E2Eテストについて考える方法を説明することを目的としているため、これらの質問とテストを作成するための一般的な戦略を、選択した任意のフレームワークに適用できます。

E2Eテストを自動化できるかどうかを尋ねる質問

E2Eテストの作成に関しては、アプリケーションでテストしているページのフローが特定の基準を満たしていることを確認する必要があります。 E2Eテストを自動化できるかどうかを判断するために、私たちが自問するいくつかの高レベルの質問を見ていきましょう。

1. APIなどの信頼できる方法で、各テストの前にユーザーデータを特定の状態にリセットすることは可能ですか? ユーザーを確実に希望の状態にリセットする方法がない場合、自動化することはできず、展開前にブロッキングテストの一部として実行することを期待できません。 また、アンチパターンであり、UIを介してユーザーを特定の状態に戻すことは通常は非決定的です。これは、速度が遅く、UIを介したステップの自動化がすでに十分に不安定であるためです。 ブラウザでページを開かなくても、API呼び出しを行ってユーザーの状態をリセットする方が信頼性が高くなります。 別の方法として、サービスが存在する場合は、各テストの前に適切なデータを使用して新しいユーザーを作成することもできます。 永続化されたユーザーをリセットするか、各テストの前にユーザーを作成する限り、ページでテストしている部分に焦点を当てることができます。

2.テストする機能、API、またはシステムを制御できますか? 請求やその他の機能に依存しているサードパーティのサービスの場合、それらをモックアウトする方法や、特定の値で決定論的に機能させる方法はありますか? フレークネスを減らすために、テストを可能な限り制御する必要があります。 他の影響を受けないように、テスト実行ごとに分離されたリソースまたはデータを使用して専用のテストユーザーを作成できます。

3.サービスまたは機能自体は、妥当なタイムアウト内で機能するのに十分な一貫性がありますか? 多くの場合、ポーリングを実装するか、特定のデータが処理されてデータベースに送られるのを待つ必要があります(より遅い非同期更新やトリガーされた電子メールイベントなど)。 これらのサービスが妥当で信頼できる時間枠内に頻繁に発生する場合は、特定のDOM要素が表示されるか、データが更新されるのを待つときに、適切なポーリングタイムアウトを設定できます。

4.ページ上で操作する必要のある要素を選択できますか? 制御できず、変更できないiframeまたは生成された要素を扱っていますか? ページ上の要素を操作するために、IDやクラス名を選択するのではなく、`data-hook`や`data-testid`属性などのより具体的なセレクターを追加できます。 IDとクラス名は、一般的にスタイルに関連付けられているため、変更される可能性が高くなります。 それ以外の場合は、スタイル付きコンポーネントまたはCSSモジュールからハッシュされたクラス名またはIDを選択しようとしていると想像してください。 サードパーティが生成した要素またはreact-selectなどのオープンソースコンポーネントライブラリの場合、これらの要素を `data-hook`属性を持つ親要素でラップし、その下の子を選択できます。 iframeを処理するために、アサートして操作する必要のあるDOM要素を抽出するカスタムコマンドを作成しました。これについては、後で例を示します。

考慮すべき考慮事項は他にもありますが、要約すると1つの質問になります。このE2Eテストを一貫してタイムリーに繰り返し、同じ結果を達成できるでしょうか。

E2Eテストを書くための一般的な戦略

1.自動化できる価値の高いテストケースを見つけます。 いくつかの例には、機能フローのほとんどをカバーするハッピーパステストが含まれます。ユーザーのプロファイル情報のUIを介したCRUD操作の実行、データを指定して結果を照合するためのテーブルのフィルタリング、投稿の作成、APIキーの設定などです。 ただし、他のエッジケースとエラー処理は、ユニットテストと統合テストでカバーする方がよい場合があります。 テストケースのリストを短くするために、前のセクションで説明した質問に答えてください。

2. APIを可能な限りセットアップまたは破棄して、これらのテストを繰り返す方法を検討します。 価値が高く、自動化可能なテストケースについては、APIを介して設定する必要があるものに注意してください。 いくつかの例は、ユーザーがページネーションに十分なフィルター可能なデータを持っていない場合、ユーザーのデータが30日のローリングウィンドウで期限切れになる場合、または成功または不完全から残ったデータを破棄する必要がある場合に、適切なデータをユーザーにシードすることです。現在のテストが再開される前にテストします。 テストは、最後のテスト実行がどのように成功または失敗したかに関係なく、同じ繰り返し可能な状態で実行および設定できる必要があります。

考えることが重要です。このユーザーのデータを開始点にリセットして、必要な機能の一部のみをテストできるようにするにはどうすればよいですか。

たとえば、ユーザーが投稿を追加して最終的にユーザーの投稿リストに表示されるようにする機能をテストする場合は、最初に投稿を削除する必要があります。

3.顧客の立場に立って、機能フローを完全に完了するために必要なUIステップを追跡します。 顧客が完全なフローまたはアクションを完了するための手順を記録します。 各ステップの後で、ユーザーが表示または操作する必要があるものとすべきでないものを追跡します。 ユーザーがアクションの適切な一連のイベントに遭遇していることを確認するために、途中で健全性チェックとアサーションを行います。 次に、健全性チェックを自動化されたコマンドとアサーションに変換します。

4.特定のセレクターを追加し、ページオブジェクト(または他の種類のラッパー)を実装することにより、変更を維持し、フローを自動化します。 機能フローを操作および実行する方法について、書き留めた手順を確認してください。 ボタン、モーダル、入力、テーブル行、アラート、カードなど、ユーザーが操作した要素に「data-hook」属性などのより具体的なセレクターを追加します。 必要に応じて、追加したセレクターを介して、これらの要素への参照を含むページオブジェクト、ラッパー、またはヘルパーファイルを作成できます。 次に、再利用可能な関数を実装して、ページのアクション可能な要素と対話できます。

5.作成したヘルパーを使用して、記録したユーザーステップをサイプレステストに変換します。 テストでは、通常、APIを介してユーザーにログインし、各テストケースが実行される前にセッションCookieを保持してログインを維持します。次に、APIを介してユーザーのデータを設定または破棄し、一貫した開始点を設定します。 すべてが整ったら、機能を直接テストするページにアクセスします。 フローの作成、更新、削除などのフローの手順を実行し、途中で何が発生するか、ページに表示されるかを表明します。 テストを高速化し、不安定さを軽減するために、UIを介した状態のリセットや構築を避け、ログインページからのログインや、UIからの削除などをバイパスして、テストする部分に焦点を合わせます。 これらの部分は、必ず`before`または`beforeEach`フックで実行してください。 そうしないと、`after`または`afterEach`フックを使用した場合、テストが途中で失敗し、クリーンアップ手順が実行されなくなり、後続のテスト実行が失敗する可能性があります。

6.ハンマーで叩き、テストの薄片を打ち抜きます。 テストを実装し、ローカルで数回合格した後、プルリクエストを設定し、すぐにマージして、残りのテストスイートとスケジュールに従ってテストを実行するか、展開ステップでテストをトリガーすることが魅力的です。 あなたがそれをする前に:

    1. まず、ユーザーをさまざまな状態のままにして、テストに合格するかどうかを確認して、適切なセットアップ手順があることを確認します。
    2. 次に、展開フローの1つでトリガーされたときに、テストを並行して実行することを検討します。 これにより、同じユーザーがリソースを踏みにじられているかどうか、および競合状態が発生していないかどうかを確認できます。
    3. 次に、Dockerコンテナでテストがヘッドレスモードでどのように実行されるかを観察して、タイムアウトを増やしたり、セレクターを調整したりする必要があるかどうかを確認します。

目標は、さまざまな条件下で繰り返されるテストの実行全体でテストがどのように動作するかを確認し、テストを可能な限り安定して一貫性のあるものにすることです。これにより、テストの修正に戻る時間を短縮し、環境内の実際のバグの検出に集中できます。

これは、「cy.login(username、password)」というログイングローバルサポートコマンドを作成したサイプレステストボイラープレートレイアウトのサンプルです。Cookieを明示的に設定し、各テストケースの前に保存して、ログインしたまま直接アクセスできるようにします。テストしているページに移動します。 また、以下に示すように、APIを介してセットアップまたは破棄を実行し、毎回ログインページをバイパスします。

終わりの考え

どのE2Eソリューションを使用するのが最適かを比較するだけでなく、E2Eテストに適切な考え方を採用することも重要です。 テストする機能が自動化の要件に適合しているかどうかについて、最初に質問することが重要です。 検証しようとしていることに集中できるように、ユーザーまたはデータを確実に特定の状態にリセットする方法(APIなど)が必要です。

ユーザーまたはデータを適切な開始点にリセットする信頼できる方法がない場合は、特定の構成でユーザーを作成するためのツールとAPIを構築することを検討する必要があります。 また、テストを可能な限り安定して一貫性のあるものにするために、制御できるものをモックアウトすることを検討することもできます。 それ以外の場合は、チームとの価値とトレードオフを検討する必要があります。 この機能は、新しいコードの変更がプッシュされたときに単体テストまたは手動回帰テストに任せる必要がありますか?

E2Eテストで自動化できるこれらの機能については、多くの場合、ユーザーの主なハッピーパスフローをカバーすることが最も価値があります。 繰り返しになりますが、タイムリーで一貫性のある方法で物事を再現可能にし、必要なフレームワークまたはライブラリを使用してE2Eテストを作成するときに、不安定さを排除します。

特にサイプレスE2Eテストの詳細については、次のリソースを確認してください。

  • サイプレステストの作成の1,000フィートの概要
  • TypeScriptサイプレステストのすべてのもの
  • サイプレステストでの電子メールフローの処理
  • サイプレステストを構成、整理、統合するためのアイデア
  • サイプレステストとDocker、Buildkite、およびCICDの統合