E2Eテスト自動化を成功に導く10のベストプラクティス

はやいものでもう5〜6年、テスト自動化の仕事をやってきましたが、同じことでも繰り返していけばいくほど新たな発見が見つかります。E2Eのテスト自動化については、2020年度版にも書いたのですが、この数年で得た経験を元に、内容は随時アップデートしていきます。

掟1. ゴールを設定する

現状、テストや品質で困っていることはなんでしょうか? そして、自動化で何を解決しようとしているでしょうか? どうやって「解決」を判断しますか?

この3つの質問の回答を、必ず用意しておきましょう

アジャイルQAインセプションデッキ(開発中)を作るのも手です。なぜここにいるのか? 結果どうなりたいのか(パッケージデザイン・Key result)? 一言でいうとどういう活動なのか(エレベータピッチ)? 自動化に限らず、品質の改善活動をまとめるテンプレとして最近使っています。

ゴールができたらアクションプランです。時間を計算できるならスケジュールもできます。スケジュールはざっくりで十分です。大切なのは計画を立てること。それによって、期待値のズレなどに気がつけるようになります(ものさしができる)。

テスト自動化は以下の流れに分割できます。

  1. ケースを作る
  2. 自動テスト環境を作る
  3. 自動テストを書く
  4. 自動テストを運用する

よくノーコードツールにすぐ契約する企業もありますが、テスト自動化は成功率が低い活動、つまり難しいアクションです。なかなか成功しにくい。

よって、まずは1〜4を簡単なスクリプトでいいので運用してから始めて、ケースを増やせるかどうかをはやく小さく確認していくのがおすすめです。

掟2. CI/CDに統合する

自動化を担当しているなら、できるだけ早い段階で、品質にかかわるメンバー全員を巻き込みましょう。品質は開発全体で考えるテーマです。共通のテーマは、民主化して当事者意識を持ってもらう必要があります。

CI/CDへの統合は、はやめに取り組むと良いです。なぜなら、開発関係者全員が関わるCI/CDパイプラインに自動テストが組み込まれることで、必要な制約となり、より一層、民主化が進みます。

CI/CDへ統合でおすすめしたいのは以下です。

  • Slackなどのテスト結果通知の統合
  • テストの自動実行の統合(PR時やデプロイ後のタイミングなど)

テスト結果をチームで確認し、テスト修正などの運用も一緒に解決していく文化を作りましょう。

掟3. シンプルに作る

シンプルなテストを作りましょう。そのためにも、テストの観点はひとつにしましょう。

ひとつのテストの中に、複数の観点(確認したいこと)あった場合、1つ目の観点でテストが失敗した場合に、2つ目の観点はテストされません。1つ目のテストが成功するまで、2つ目の観点確認ができなくなってしまいます。

テスト間に依存関係があると、あるテストがあるテストに影響を与えてしまい、テストが不安定になってしまうため、独立性を高めたほうがよいです。

しかし、データの登録と削除は、「登録しないと削除できない」ジレンマに陥るため、1ケースに詰め込んでもいいでしょう。

もし、APIでデータ作成ができるなら、観点がひとつになり、より独立した小さなテストに分割できます。

例:
    - APIでデータを登録して、表示を確認するテスト
    - E2Eでデータを作って、APIでデータの存在を確認するテスト

そして、コンピュータは、小さな作業を並列で繰り返しやるのが得意です。このメリットを活かすなら、テストは小さく作りましょう

テストを小さくするため、目標実行時間を決めるのも手です。たとえば、僕の場合、まずは5分以内に終わるテストを目指します。それでも無理なら10分です。

ひとつひとつのステップ(画面の1操作)も小さくしたほうがいいです。たとえば、100のテストが利用する共通処理があった場合(掟6. 同じ操作を2回するなら部品を作る)、そのひとつのステップに10秒かかる場合、

ステップの時間 10秒 x 利用されている数 100ケース = 1000秒 = 16.66分

の時間が合計でかかります。ステップの時間が1秒少なくなると1.66分削減。半分になれば8分以上削減と、テストの規模が大きくなればなるほど削減コストも大きくなります。

なにをテストにするかは、最近だとリスクベーステストが流行ってるみたいです。

掟4. タイミングを意識する

最近流行りのビジュアルリグレッションテストでない場合、自動テストは振る舞いを確認するのが得意で、見た目の確認が苦手です。たとえば、今どのページにいるかを自動テストは教えなければ理解できません(そもそも非同期読み込みが中心の現状では「ページが読み込まれた」ことの確認も難しい)。

画面遷移したとき、モーダルが表示されたとき、おしゃれなプルダウンやメニューを開いたときなど、画面の形や構造が変化した場合に、今どういう状態なのかをアサートする必要があります

アサートはシンプルに、「〜が表示されていること」を確認します。

また、WebやモバイルアプリのE2Eにおいて、テスト失敗の原因のほとんどが「タイミング」です。

画面ごとのアサートと同時に、表示のタイミングをうまくコントロールする必要があります。

表示タイミングを調整するために、固定でウェイトを入れることもできますが、次に操作する要素が表示されるまで待つほうが効率的です

掟5. 大切なものだけアサートする

前述の通り、自動テストは見た目のテストが苦手です。テストの目となるものがアサート(アサーション、確認項目)です。

一つの画面でいろいろな確認をしたくなると思いますが、すべてを確認するのは大変です。よって、このテストで本当に確認したいことを確認しましょう。観点があるのであればその観点に紐づくアサートを入れましょう。

「せっかくだからついでに・・・」とアサートを増やすと、観点が変わってしまう可能性があります。そういう場合は、新しく増やしたい観点でケースを作ります(掟3. シンプルに作る)。

あとは、ビジュアルリグレッションテストが使えるのであれば、「正しく表示されること」は、ビジュアルリグレッションテストにまかせてしまうのも手です。一度確認しておけば、差分があればすぐに検知できるはずです。

掟6. 同じ操作を2回するなら部品を作る

自動テストにもDRY原則(Don’t Repeat Your Self:繰り返しを避ける)を適用すべきです。2回同じことをするならそれは部品にして再利用しましょう。

僕の場合、まずは3つの部品種別に分けて作ります。

  • 遷移の部品: 遷移のリンクやボタンをクリックして、目的の画面への遷移が完了するまでの部品です。
  • 処理の部品: ログイン情報をいれてボタンを押し、成功し、成功後の画面遷移が完了するまでの部品。成功と失敗に対応するなら遷移先を分岐させるか、処理と遷移先で部品を分離する必要があるが、大抵の場合、処理成功ケースだけで事足りるものです。
  • アサートの部品: 確認したい大切なことだけ確認します(掟5. 大切なものだけアサート)。

最終的に、自動テストのほとんどが部品で構成されるようになり、ひとつひとつの部品の品質を高めることで、よりテスト全体が安定していきます。

掟7. データとテストを分離する

テストはデータに依存します。そのため、どのようにテストとデータを分離するかをあらかじめ考えておくと良いです。たとえば、以下のようなデータの分離方法が選択できるはずです(上位ほど難易度やコストが高い)。

  • 個別のテストごとに、テスト環境を作る(そして、テストが終わったら環境も消えると効率的)
  • 実行したいテスト群ごとに、テスト環境を作る
  • テスト自動化用のテスト環境を作り共有で使う
  • みんなのテスト環境を使う

共有のテスト環境の場合は、その中でデータを分離できないかを考えます。

  • ユーザごとに表示が別れているなら、ユーザで分ける
  • テナントごとに表示が別れているなら、テナントで分ける(たとえば、ECの場合、店舗を分ければ商品データを分離できる)

環境内での分離ができないならば、テストごとにユニークな文字列(例: 藤原大_sFw5sxg)を入力しましょう。これによって、そのデータがどのテストのものなのか特定しやすくなります。

それ以外だと、編集系のテスト(あるデータが存在しないとできないテスト)などは、データとしてあらかじめ作成し、特定のテストだけが修正するルールにしておくとまずは良いと思います。

ただし、データの分離が弱い場合(共有環境など)、その環境のデータが消えたり、操作されるリスクがあることをチームで理解し、運用でカバーする必要があります。

掟8. がんばりすぎない

最近のテスト自動化サービスやフレームワークでは、条件分岐、ループといった便利な機能が利用できます。これによってテストはとても柔軟に作成できます。

しかし、柔軟性にこだわりすぎて、テストが複雑になってしまう危険性も伴います(掟3. シンプルに作る)。

よって、どの程度まで柔軟性をもたせるか? 便利な機能を使うか? を決めておくとよいでしょう。たとえば、条件分岐やループは1階層のみに絞り、「IF文の中にIF文」といったネスト構造を避けます。

僕の場合、データ編集系のテストで条件分岐を有効活用しています。たとえば、「もしもデータがAAAAならBBBBを入れる」または「BBBBならAAAAを入れる」といった分岐があれば、テスト失敗しても、いちいちデータをAAAAやBBBBといった直前の状態ににもどさなくてよくなり、再実行可能なテストになります。

ループは基本的にあまり使いません。連続登録や連続削除など、観点をしぼって実装すると良いと思います。

自動テストは、たくさんの似たような要素の中から特定のひとつを見つけるのが苦手です。そういった場合は、XpathやCSSセレクタを指定して、柔軟に要素を特定するといいと思います。

たとえば、Xpathであれば、指定した文字列が含まれている要素を探せる「contains」を使うとかなり柔軟に検索できます。

例: 
  NG: //form/button[text(), '登録']
  Good: //*[contains(text(), "登録")]

また、テストの安定化を考えるために、なぜE2Eテストでidを使うべきではないのか を読むことをおすすめします。E2Eにおける要素特定のトレンドを学べるはず。

掟9. 情報を残す

テスト名、テストの説明だけで、そのテストの意味を語り尽くすのは難しいはずです。

相手に伝わるテストを作るために、ステップの間にコメントを残しましょう。特にXpathやウェイトは、それだけでは意図が伝わりません。

それ以外でも、ぱっと見ただけでどういうテストかわかるように、プラン名・テスト名を工夫したり、カテゴリやラベルを活用しましょう。

命名規則も重要です。

テストやそれ以外のデータの命名ルール。階層構造の設計等がきちんとできていると、はじめて見る人にもすぐ理解できる状態になるはずです。

掟10. 実行タイミングを設計する

インセプションデッキにもまとめましたが、自分たちのプロセスを整理し、どこで何を実行するかを検討します

自動テストは実行すればするほどその恩恵が大きくなります。リリース前に自動化されたリグレッションテストを流すのであれば、リリース回数が多い環境ほど役に立つはずです。

しかし、テストの実行回数が増えるに比例して、テスト結果の確認コストが増えます。テストが安定していない場合は、コストがより増えます。月額実行回数で金額が決まるサービスを利用する場合、サービス利用コストも増えます。

逆に、実行回数が少なすぎると、テスト結果というフィードバックを受けるタイミングも遅くなるため、バランス感覚が必要です。

実行タイミングは大きく、以下の種類にわけられます。

  • コミットごと => 特定機能やその周辺機能の確認用
  • デプロイごと => QAフェーズ前のリグレッションテストとしてなど
  • リリース前 => リリース前の最終確認として
  • 定期実行 => 定期チェックによるアプリのヘルスチェックとして

これらを考慮して適切な実行タイミングを設計しましょう。まずは、効果が出やすいリグレッションテストの整備からはじめるのがおすすめです。

改めて見直してみると、いくつかの掟をマージできたり、いくつかの掟をブラッシュアップできた気がします。これらのプラクティスが全てではないかもしれませんが(ベストプラクティスは「その時の」ベストでしかありませんから)、少しでもお役に立てれば幸いです。

“E2Eテスト自動化を成功に導く10のベストプラクティス” への 1 件のフィードバック

コメントは受け付けていません。