
現在は「VUCAの時代」と言います。VUCAとはVolatility(変動性)、Uncertainty(不確実性)、Complexity(複雑性)、Ambiguity(曖昧性)の頭文字をとったビジネスシーンで使われる言葉です。これら4つの言葉が表すとおり、「未来の予測が難しい状況」を表しています。
過去を振り返ると、使い古された言葉になりますが、高度経済成長時代に象徴されるように「作れば売れる」時代でした。しかし、VUCAという言葉が登場したように、現在は、「何が売れるかわかりにくい」状況に陥っています。
この連載では、現在やこれからの時代で求められるであろうソフトウェア開発における「品質」を再定義し、あるべき姿への道筋を示し、代表的なプラクティスなどを紹介しながら、アジャイルQA(アジャイルな品質保証、もしくは品質合意)という活動や、具体的な手段としてアジャイルテスティングのあり方を議論していきます。
最終回である第4回目のテーマは、E2Eテスト自動化の10のベストプラクティスを探求します。
1. 小さく。独立。観点はひとつ
小さく、独立した、観点がひとつだけの自動テストを作りましょう。
「小さく」は文字通りテストの大きさを小さくします。E2Eテストだとシナリオによっては長くなりがちですが、可能な限り短くしましょう。たとえば、毎回ユーザデータをE2E経由で作成するのではなく、API経由でワンステップでユーザ作成してテスト実行すれば、クリーンなユーザで毎回テストできます。
実行時間は、長くても5〜10分以内に終わるのが良いでしょう。たとえば、30分のテストがあって、29分目でテストが失敗した場合、また29分やり直すのは辛いはずです。短ければ短いほど、フィードバックサイクルも短くなります。長いシナリオは短くリファクタリングしましょう。
「独立した」テストによって、並列実行できるようになります。極端な例になりますが、1分かかっていたテストが1000件あれば、ひとりでやると1000分かかってしまいます。クラウドの恩恵によって、マシンを1000台並べれば1分で終わらせられます。
「観点がひとつ」も理想です。そうでなければ、テスト失敗時に、どの観点が成功して、どの観点が失敗したかを、毎回判断しなければなりません。
人間がやるテストのように、あっちもこっちも効率よく確認したくなるものです。しかし、機械は単純な小さな作業をたくさん並列に実行するのが得意です。可能な限り観点をひとつにしましょう。
ただし、シナリオによっては観点が複数あると便利なものもあります。たとえば、データの登録処理と削除処理は、お互いに依存する部分があるため、「データを登録してから、削除する」シナリオでもいいかもしれません。APIを使えるなら、「データ登録」と「APIでデータ作成して削除」の2シナリオでも素敵です。
2. 必要なだけ待って、大切なものだけアサート
現代の自動テストはかなり高速に実行できるようになってきました。そのぶん、テストの不安定さも増してゆきます。なぜなら、自動テストは画面が読み込まれるタイミングを取るのが苦手だからです。
たとえば、最近のアプリは、非同期で画面のパーツをそれぞれ読み込みます。モーダルでふわっとメッセージを出したり、クリックするとメニューがスライドしてきたり、使い勝手もとてもよくなってきました。
テストを高速実行すると、この「ふわっとした動き」や「非同期の読み込みによるタイミングのズレ」によって、テストが失敗します。また、サーバスペックが低かったり(DEVやSTGはサーバの性能を抑えるものです)、ネットワークが一時的に重い場合も、テストに失敗しやすくなります。
よって、意図したページに遷移していることや、意図したコンポーネントが読み込まれていることを、効率的に「待つ」のが重要になります。
最近のツールやフレームワークでは、「〜まで待つステップ」などが実装されているはずです。「固定でWait」をできるだけ避けましょう。
確認したいことがたくさんある場合、どうするのがよいのでしょうか? 人間であれば上から下まで目で追っていくだけで確認できるかも知れません。しかし、自動テストでは人間がきちんと「何をしてほしいか」を教えなければなりません。
だったら、本当に確認したいことだけアサートしてみてはどうでしょうか?毎回表示される項目すべてを確認するのは大変なので、ビジュアルリグレッションテストを活用してもよいかもしれません。最初のスクリーンショットだけ確認して、あとはそれに差分が出たときだけ見れば問題ないはずです。
3. 同じ操作を2回行うなら部品化
自動テストにもDRY原則(Don’t Repeat Your Self:繰り返しを避ける)を適用すべきです。同じことを2回やるなら、まよわず共通部品を作り、みんなでそれを再利用しましょう。
部品はどんどん磨いていきます。ピカピカの部品は、テストの安定化に貢献してくれます。
以下のように部品を設計してもいいでしょう。
- 共通の部品: 共通処理をまとめる
- 遷移の部品: 遷移する動きだけ部品にする
- 処理の部品: ログイン処理、ユーザ登録処理といった処理を部品にする
- アサートの部品: 確認したいことを部品にする
これらの部品を組み合わせるだけで、大抵のテストは作れるはずです。
4. 誰が見てもわかるテストを作る
テストは誰が見ても理解できる内容にしましょう。観点をひとつにするプラクティスを活かし、コメントやアノテーションによって、ひと目でどういうテストかわかるようにします。
5. テストデータを分離
テスト環境がひとつしかない場合、あるテストが更新したデータの影響で、他のテストが失敗してしまうケースもでてきます。可能であれば、テストデータを独立させるために以下の対応を検討すると良いでしょう。
- テスト環境を分ける
- テスト開始時にテストデータを流し込む。最後にデータを消す
- ユーザを分ける
- テストデータに目印を入れる
テストデータの流し込みと削除ができると、毎回クリーンな環境でテストできます。
テスト環境を複数用意したり、一時的なテスト環境を作り、テスト後に環境ごと削除する方法も一般的になりつつあります。
ユーザを分けるのはシンプルな方法です。管理ユーザ、一般ユーザなど、それぞれのユーザパターンを用意するだけで、データをある程度分離できます。
最終手段はテストデータに目印を入れる方法です。たとえば、テストIDなど実行時に一意のIDを作成し、ユーザ作成時の名前に「藤原-${一意のID}(例: 藤原ーag456ad など)を入れてあげれば、自分が作ったデータがすぐわかります。
とくにデータの一覧など表形式の画面の場合、データ作成のタイミングによっては、期待する位置に表示されない場所があるため、「//*[contains(text(), ‘${一意のID}’)]]」で探すとよいでしょう。
6. テストはシンプルに
最近のテスト自動化フレームワークを使うと、条件分岐やループといった処理が簡単に実装できます。しかし、プログラミングと同様、多用するとテストの複雑度が増すため、注意が必要です。
たとえば、「データの更新」を確認するテストだと、以下のように条件分岐を使ってわかりやすいテストに仕上げられます。
まず、あらかじめ更新するデータを作成しておきます。そのデータが何かを調べ、条件分岐を使って、AだったらB。BだったらAに更新します。
ループは基本的に使う必要はないはずです。ただ、ごくまれに自動テストでボタンをクリックしても反応しないケースもあるので「うまく遷移しない場合はリトライ」といった使い方だと便利です。
表形式や複雑な画面の場合や、似たような要素が並ぶため、要素を特定するのは、AIでも人間でもとても困難です。そういう場合は、XPathやCSS指定の要素検索や、Javascriptを駆使して探す方法もあります。
XPathやCSS指定の場合は、可能な限り柔軟な指定方法にしましょう。たとえば、
//form/button[text(), ‘登録’]
と書くよりは、
//*[contains(text(), “登録”)]
と書いたほうが画面の変化に柔軟です。
画面上であれば、大抵のことがJavascriptでできます。ただし、やりすぎるとテストが複雑になってしまうので、最終手段として考えましょう。
7. すべての環境でテストする
最適な部品で構成された安定した自動テストを有効活用しましょう。
- コミットごと
- PR作成ごと
- デプロイごと
- リリースごと
- 定期実行(毎日夜間など)
のタイミングで、洗練された自動テストを実行するのが効果的です。
何回も繰り返しテスト実行するだけでなく、たとえば、DEV・STG・本番環境ごとに、自動テストを使い回す方法も取れます。アプリケーションやシステムの環境によると思いますが、環境が変わっても動作する自動テストを作りましょう。
最終的に、本番でも自動テスト実行できるようになれば、安心感がより高まるはずです。
8. テスタブルなシステムを目指そう
「テスタブル(テストのしやすさ)」は重要な指標です。システムがテスタブルになると、テストのカバレッジが一気に高まります。
たとえば、以下のようなアクションからはじめてみるといいでしょう。
- 簡単にテストデータを作れる・消せる、QA用APIを作る(のちにQA用ツールとしてまとめてもよい)
- iframe、onmouse属性、hover擬似クラス、ブラウザに依存したアクション(戻る、進む、リロード)は、テスト自動化で問題になりやすいため利用をよく考える
- 問題が起きたときにすぐに原因究明できるログや、失敗時のスクリーンショットや動画をまとめたレポートページを用意する
9. E2Eを作りすぎない
E2Eテストはバグを見つけるテストではありません(E2Eの時点でバグが見つかってしまうのは遅すぎる!)。定期的な修正による影響範囲を確認するのに最適なテストです。つまり、「壊れていないこと」を確認するテストとも言えます。
最近のテストフレームワークやSaaS型のテスト自動化サービスによって、E2Eテストはかなり作りやすくなりました。これは同時に、「不必要なテストをたくさんつくってしまう」問題も含んでいます。
どれだけE2Eテスト作成が楽になっても、良いテスト自動化の戦略や、良い自動テストの設計は考えていく必要があります。良い戦略や設計がなければ、いまいちなテストがたくさんできてしまいます。
E2Eテストでバリエーションを求めると、テスト数が膨大になってしまいます。バリエーションは単体テストやAPIレベルのテストで担保するなど、テストが増えない対策を考えていきましょう。
もし、すでにリグレッションテストをお持ちであれば、本当に全部自動化すべきか考えましょう。 全部を自動化するのは、とても難しく険しい道のりです。新しくテストを作る前や、マニュアルテストを自動化する前に「作るべきか?」、「コスパに見合うのか?」を問いかけてみましょう。
「せっかくテストがあるから捨てるのはもったいない。自動化したい」という方もいますが、自動化するとそこから運用コストがかかります。テストが安定しない環境だと、定期的にテストが失敗し、確認コストがかさんでしまいます。大切なのは、そのテストが本当に価値が高いものなのか?です。毎回成功するバグを見つけないテストの価値は、バグがよく見つかるテストより低くなります。
筆者の経験だと、リグレッションテスト全体を定義し、優先順位をつけて実装を進めていくと、約30%ぐらいのカバレッジで、バグやリグレッションを十分検知できるようになってきます。はじめから「全部」ではなく、「必要な分だけ」と考えるのがポイントです。
10. 品質活動を民主化しよう
たとえば、私がテスト自動化の支援を行うときは、以下のようなスケジュールを作るケースが多いです。
- 1ヶ月目:
- テスト自動化のゴールを設定する
- テスト自動化環境を用意する
- 自動テストの基本的な実装方針を決める
- とても重要な5ケースを実装する
- テストの定期実行を行う
- 2ヶ月目:
- 実装経験をもとに実装方法のトレーニングを広めていく
- 定期実行を行いながら運用改善を進め、ケース数を10〜20ぐらいに増やす
- 3ヶ月目:
- CI/CDに結合して実運用に近づける
- 定期実行を行いながら運用改善を進め、ケース数を30〜50ぐらいに増やす
- 3ヶ月間のふりかえりを行い、導入検証を終える
ポイントは以下です。
- 関係者全員で簡単なテストを作り、自動テストで何ができて何ができないかを理解する
- テスト結果を開発チーム全員がいるSlackに通知したり、CI/CDに統合することで、自分たちの開発プロセスにテストを統合していく
- 定期的にテスト自動化活動のレビューを行う
品質改善活動は、開発チーム全体の活動です。品質に係る活動はオープンに、より民主的に進めることで、品質やテストが誰にとっても重要な活動になっていきます。
まとめ
今回は、E2Eテストのベストプラクティスをまとめてみました。ベストプラクティスも時代とともにどんどん変化していくものだと思います。ぜひ、どんどん試しながらプラクティスをアップデートしていってもらえればと思います。
連載「アジャイル・DevOps時代に求められる「品質」を再考する」は今回が最終回となりました。
- 第1回 アジャイル時代に求められる「品質」とは何か?
- 第2回 アジャイルQAのロードマップ
- 第3回 アジャイルQAプラクティス
- 第4回 E2Eテスト自動化ベストプラクティス
と、アジャイル時代の品質を考え、アジャイル開発に適したQAプロセスへの道のりを整理し、実践のためのプラクティスを考え、最後にテスト自動化の具体的なプラクティスを考えました。
アジャイルQAの時代ははじまったばかりです。残念ながら、これまで書いてきたこともどんどん古びてしまうでしょう。ぜひ、ご自身が発見した経験や知見があれば、どんどん発信していただければと思います。たくさんの人達のアクションによって、テスト自動化、あるいはアジャイルテスティングが「当たり前」になる時代がやってくると信じています。