
前回のおさらい
前回の記事では、E2Eテストの自動化において最初に気をつけるべき目的の設定と毎日テストを実行することの重要性、そして導入のステップについてお伝えしました。第2回となる今回は、実際に毎日の自動テストの運用を始めてから遭遇しがちな具体的な課題と対策についてお話ししたいと思います。
◆連載|テスト自動化の習慣を最速で定着させるためには 第1回:E2Eテストの自動化を最速で成功させる秘訣 第2回:毎日の自動テストを無理なく続けるためのキーワード 第3回:共通処理を活用してさらに効率的に自動化を進めよう
運用時にありがちな課題
自動テストの運用で、必ずと言っていいほど出てくるのが以下のような課題です。
失敗したテストの解析に時間がかかる
自動テストは実行したら当然結果を確認し、失敗したテストがあればアプリケーションの不具合によるものなのか、テストケースに誤りがあるのか、または環境要因かを切り分けてそれぞれ対処する必要があります。毎日の作業なので、ここに時間がかかり過ぎると「自動テスト=つらいもの」という認識が生まれ、自動テストをさらに有効活用していこうというモチベーションが失われてしまいます。
Flakyなテスト(結果が一定にならず、成功したり失敗したりするテスト)がある
実行の内容やどのようなアサーション(結果の確認)を入れているかにもよりますが、「同じ手順で実行しているはずなのになぜか時々失敗してしまうテスト」というのは非常によく発生します。前述の「失敗したテストの解析」をひときわ難しくするのがこのFlakyなテストです。原因はテスト対象のアプリケーションのレスポンスタイムのちょっとしたずれ、ブラウザのバージョンアップなど様々で、筆者が経験した中では「テスト用のPCでウィルスチェックが走って動作が重くなったため」というものもありました。
実行時間が長い
E2EテストはUnitテストに比べてどうしても実行時間が長くなりがちです。そのため前回記事の冒頭でも「テストのピラミッド」として紹介したようにそもそも数を多く作りすぎないことも重要なのですが、必要なテストだけでも数時間となってしまうこともあります。すると前日の開発分のテストが翌日朝に終わらないという状況になり、フィードバックが遅れることで自動テストへの対応が遅くなる→メンテナンスしづらくなり陳腐化するというリスクがあります。
これらの問題をすべて解決する銀の弾丸は存在しませんが、意識しておくべきかどうかで大きく結果が変わってくるのが「テストケースの独立性」というキーワードです。
独立性とは?
「良い単体テストの条件」として有名な「F.I.R.S.Tの原則」というものがあります。それぞれFast(迅速)、Isolated/Independent(独立)、Repeatable(繰り返し可能)、Self-validating(自己検証可能)、Timely(タイムリー)の頭文字を取っています。単体テストとE2Eテストでは前提条件が大きく異なりますが、E2EテストでもIndependent(独立)とRepeatable(繰り返し可能)の原則はとても重要です。テストが独立していて繰り返し可能であるということは、つまり日次実行のときと同じ順序で実行する必要がなく1ケースだけで実行可能であり、何度実行しても同じ結果になるということです。
これが達成されていると、以下のようなメリットがあります。
- 失敗したときに素早く単独で再実行できる:テストケースが独立していると、失敗したテストだけを再実行することが容易になります。これにより、毎日の解析と修正が迅速に行えるようになります。
- Flakinessにも対応しやすい:上と同じ理由で手軽に再実行できるためどれくらいFlakyであるかを簡単にチェックできるというメリットが1つあります。加えて、そもそもテストが繰り返し実行可能でないこと自体がFlakinessを生んでいる場合も多い(前回のテストで生成されたデータを正しく削除していないと次回のテストが失敗する等)ため、対処すべきFlakinessが減るというメリットもあります。
- 実行時間を短くできる:独立性が保たれているテストケースは、(多くの場合)並列実行が可能になります。その結果、テスト全体の実行時間が短縮され、開発者に素早いフィードバックを提供できます。
いかがでしょうか。ありがちな課題に応えられているように見えますね。
具体的に独立性を保つための工夫
では、テストケースの独立性を保つための具体的な工夫を紹介していきましょう。必要に応じて、AIを利用した自動テストサービス「MagicPod」を使ってどのように設定ができるかも一緒に見ていきます。
開始時の状態に依存しない
「独立性を保つ」とほとんど意味は同じなのですが、ここではテスト対象のアプリケーションを操作する上で開始時にどういう状態になっているか、というような意味でとらえていただければと思います。代表的なものとしては、「ログインしている」「ログインしていない」のような状態の違いが考えられますね。もしくは、「最初に必要なチュートリアルを終えている」「終えていない」といったものもあります。
たとえばテストケースの最初に「ログイン画面でIDとパスワードを入力してログインする」といったステップを入れてしまうと、アプリケーションの仕様にもよりますが実行開始時にすでにログイン済みだった場合は違う画面に遷移してしまって失敗することが多いでしょう。状態に依存しないテストにするためには、「(ログイン後でないと開けない)マイページに遷移する。もしログイン画面が表示されたら、IDとパスワードを入力してログインする」といったように条件分岐を使えばOKです。

実際に両者のテストケースを作成してみるとこんな風になります。
データ・アカウントを分ける
これは特に全体を並列実行したいときに重要な項目です。複数のテストケースで必要なデータを共有してしまうと、1つのケースを変更したときに他のケースが動かなくなってしまい非常にメンテナンスしづらくなります。表示確認するだけのようなケースならそれほど問題ありませんが、大抵のテストではデータに何らかの変更を加えてその結果を確認すると思いますのでケース毎に分離させるのは重要です。また、テスト対象のシステムにもよりますが多くのシステムではアカウント(ユーザ)毎に異なるデータを持ちますのでアカウントから分けてしまうのも手です。あまり分けすぎると認証情報などの管理が大変になるので、筆者のチームでは
- アカウントの特性によらない一般的な操作のテスト→汎用のテスト用アカウント
- 外部ID連携、エンタープライズユーザなどアカウントの特性に合わせたテスト→ケース毎の専用アカウント
といった分け方で運用しています。
使用するデータは極力テストケース内で作る
前の項目と似ていますが、さらに繰り返し可能性を高めるために「ケース1ではデータAを使う」というような分離ではなく「ケース1を実行するときは毎回必要なデータを生成する」という仕組みにしておくと便利です。こうしておけば、実行時に何らかの不具合でデータがおかしくなったとしても次回実行ではクリーンな状態で始めることができます。
「毎回データを作る」というとそれだけで実行時間が長くなってしまいそうな気がしますが、テスト対象のシステムにデータを登録できるAPIがあれば素早くデータを準備できます。MagicPodには「Web APIコール」というコマンドがあり、ブラウザの操作とは別に任意のAPIを実行することができます。この機能を使うことで、画面操作だけでは実現が難しかったり時間がかかりすぎたりする操作も簡潔に行えます。

変数の活用
データの話が続きましたが、色々と工夫を重ねても毎回全く同じ結果にはできないようなものもあります。日付が絡む処理や、ニュースのように日々変わる内容の表示などです。こういった固定できない内容を使ったテストでは、変数を活用しましょう。
たとえば、ホテルの予約ページのテストをする際に毎回未来の日付を入力しなければいけないとします。下図のように日付を格納する変数(ここでは「DATE」という名前)を用意し、常に2日後の日付を入れるようにすればテストを実行するたびに適切な日付を入力できます。

また、ニュースの見出しが記事の一覧画面と詳細画面で一致していることを確認するなら、一覧画面で見出しの内容を変数「TITLE」に保存しておき、詳細画面の見出しと比較することができます。

テスト環境の日付やニュースの内容もテスト環境の構築方法によっては頑張って固定化できなくもないですが、あまりに固執しすぎると特定のデータで起きる不具合を見逃す可能性もあります。変数を使って緩やかにテストできる部分では積極的に使ってみましょう。
毎回同じ環境で実行する
こちらは少し毛色が変わって、「独立」よりも「繰り返し可能」に重点をおいたポイントです。E2Eの自動テストはとにかくちょっとした外部要因で結果が変わりやすいので、外部要因の差を排除したクリーンな環境で実行することが大切です。
最近はクラウド環境で指定のブラウザ・デバイスでテストできるサービスも沢山あります。実行環境の整備はそれだけでかなりの手間がかかりますので、テストの内容に集中するためにも環境を安定させるのはそういったサービスに任せてしまったほうが良いでしょう。
毎回同じ環境でテストを実行しているとスクリーンショットも基本的にまったく同じになるので、下のように期待値の画像とピクセル単位で比較することも可能です。

こちらは上の2つの画像から差分だけを抽出したものです。レイアウトに変更があった箇所だけがハイライトされ、OKかどうかの確認がしやすくなっています。

まとめ
今回は、自動テストの運用を無理なく続けるために意識すべきテストの独立性についてお伝えしました。「独立」というキーワードを意識することで、実行時間の長さ・解析時間の長さ・Flakyなテストによる苦痛などをある程度解決することができます。テストツールによって解決できる課題もありますが、どんなデータを使ってどのようにテストケース間の依存を防ぐかという設計の部分はツールによらず工夫が必要なのでテストエンジニアの腕の見せどころです。
次回は、さらに短い時間で自動テストの恩恵を受けるためのテストケース作成時の工夫をお伝えします。
連載一覧
第1回:E2Eテストの自動化を最速で成功させる秘訣
第2回:毎日の自動テストを無理なく続けるためのキーワード
第3回:共通処理を活用してさらに効率的に自動化を進めよう