テスト自動化における 10 のベスト プラクティス #3: メンテナンス可能なテストを作成する
テストの自動化で最も難しい点のひとつは、UI(ユーザーインターフェース)の変更に合わせて既存のテストをメンテナンスすることです。
もうひとつは、「Flaky(不安定)なテスト」の特定と改善です。Flakyなテストとは、テスト対象アプリケーション (AUT) とは無関係な理由で、成功も失敗もするテストを指します。
今回の記事では、このような課題に対応してテストのメンテナンス工数を削減するためのテストケースの設計および、レコーディング、実行方法について説明します。
メンテナンスを最小限におさえるための設計
テスト方法を決定する前に、テスト対象を決定する
テストケースを適切に設計することで、メンテナンス工数をおさえることができます。まず、テストすべき機能を特定することから始め、次にその機能のテストを一連のステップ(操作手順)に分解して、期待される結果を明確に定義します。その後、「手動で実施するテスト」と「自動化すべきテスト」に振り分けます。
※自動化に最適なテストケースについては、本シリーズの第 1 回「テスト自動化における 10 のベスト プラクティス #1: 何を自動化するか」を参照ください。
テストケースを文書化する
テストケースを文書化することにより、「テストの事前条件」、「実行手順」、「期待される結果」が考慮され、適切に設計されていることを保証するのに役立ちます。また、テストケースのテンプレートやTestRailなどのテスト管理ツールを利用することで、テストケースの資料を体系化してまとめるのに役立ちます。
テストケースを単純にする
理想として、テストケースは1つの機能のみを検証し、1つの理由のみで失敗するべきです。
複雑なテストケースは、「Flakyなテスト」になる確率が高くなります。多くのステップを必要とするテストケースは、テストケースを分割するよう検討しましょう。
命名規則を使用する
UI要素とテストで使用するオブジェクトの名前は、一目で分かるものにするべきです。テストケースやテストステップを文書化する際にコメントが必要な場合は、テストケースが複雑過ぎないか、そして単純化する必要がないかを検討しましょう。
メンテナンスを最小限におさえるためのコーディング
モジュラーな構造を使用する
テストケースは、他のテストケースとできる限り依存しないようにするべきです。
たとえば、「Web ストアの支払い処理を検証するテストケース」はその前の「ユーザーの買い物かごに商品を入れるテストケース」に依存するべきではありません。
テストケースの独立性を保つと、テストのメンテナンスが簡単になるだけでなく、並列実行や分散実行を行うことができます。ただし、どうしても他のテストケースに依存しなければならないテストケースがある場合は、テスト自動化フレームワークの機能を使って、必ず適切な順序でテストを実行するようにしましょう。
UIの変更に強いテストを作成する
UIに変更があった場合でもテストを正しく動作させるには、UIオブジェクトを検出するために位置の座標に頼らないことです。さらに、Webアプリケーションをテストしている場合、UI要素の位置を得るためにページのHTML構造や動的なIDに頼るのは避けましょう。理想は、テスト対象アプリケーションの開発者がUI要素の固有ID(ユニークな情報)をアプリケーションに含めることです。
※Ranorex(Ranorex SPY)では、固有IDがない場合、安定したテストにするため、最も効率的な方法でUI要素を特定します。
アプリケーションの機能単位でテストをグループ化する
アプリケーションの機能単位でテストケースをグループ化することで、ある機能に変更があったときにテストケースの更新が容易になります。また、その機能に対して部分的に回帰テストを実行することもできます。
※Ranorex(Ranorex Studio)では、再利用可能な機能を「ユーザーコード」機能によってメソッド化し、共有ライブラリのように使用することができます。また、個々のメソッドに対してコメントを付けることもでき、テスターがメソッドを利用する際に役立ちます。
テストコードをコピー&ペーストしない
複数のテストシナリオにおいて、アプリケーションで同じ操作がある場合、再利用できるテストスクリプトを作成しましょう。たとえば、アプリケーションを起動するテストスクリプトは 1つにするべきです。そして、このテストスクリプトを他のテストケースでも再利用しましょう。これにより、アプリケーションの起動処理に変更があった場合、1つのテストスクリプトを更新するだけで済みます。
※Ranorex(Ranorex Studio)は、キーワード駆動型テスト、ローカル/グローバル パラメーター、および条件付きテスト実行をサポートします。Ranorexを利用すれば、個々のテストスクリプトから高度なテストケースを簡単に作成できます。
テストスクリプトをテストデータから分離する
テストスクリプトにデータ値をハード コーディングするのは避けましょう。代わりに、外部ファイルにテスト用のデータ値を格納し、変数またはパラメーターを使って外部ファイルをテストに渡しましょう。
※データ駆動型テストについては、「Ranorex ユーザーズガイド」を参照してください。
ソース管理システムを使用する
共同でアプリケーションコードを開発したり、必要に応じて前のバージョンのコードに戻したりするために、Git、Subversion、Microsoft TFS(Team Foundation Server) といったソース管理システムを利用します。可能であれば、アプリケーションコードを管理するソース管理システムと同じシステムを使って、テスト資産を管理するべきです。
メンテナンスを最小限におさえるためのテスト実行
安全なテスト環境を用意する
信頼性の低いサーバーやネットワーク接続は、通常であれば成功するテストを失敗させることがあります。テスト対象アプリケーション自体には関係のない潜在的な失敗ポイントを排除するために、モックサーバーの使用を検討してください。
セットアップ/ティアダウンのプロセスを使用する
セットアップのプロセスを使って事前条件を処理し、テスト対象アプリケーションをテスト実行のために適切な状態にしましょう。セットアップのプロセスは通常、アプリケーションの起動、ログイン、テストデータのロード、およびテストに必要な事前準備を処理します。また、ティアダウンのプロセスを使って、テスト実行が完了した後にテスト対象アプリケーションを適切な状態に戻しましょう。これにはテストデータの消去も含まれます。
より早く失敗する
効率的なテスト設計のためのもう1つの基本方針は「Fail Fast(より早く失敗すること)」です。テストを停止すべき重大な問題がアプリケーションに存在する場合、テストの実行を続けるのではなく、直ちに問題を特定すべきです。適切なタイムアウト値をテストに設定して、UI要素の探索にかける時間を制限しましょう。
失敗によるテスト実行の停止は必要な場合だけにする
テスト実行をすべて停止するのは、必要な場合だけにしましょう。
1つのエラーでテスト実行を停止するのは、時間の無駄になりかねません。また、テスト実行を途中で停止すると、他のテストケースが成功するかどうかが分かりません。
※Ranorex(Ranorex Studio)には、エラーの後にテスト実行を停止できるだけでなく、エラー後に実行を継続するための 3種類のオプション(次の繰り返しに移動して続行、次のテストケースに移動して続行、次の親テストケースに移動して続行)が用意されています。
これらのオプションの詳細については、「Ranorex ユーザーズガイド」を参照ください。
失敗を期待するテストを分離する
成功を期待するテストだけを実行しましょう。未解決の問題が含まれるテストにおいては、それらのテストケースをメインのテスト実行から外し、別に実行しましょう。
これにより、メインのテスト実行に本当の問題があるかどうかを判断するのが楽になります。同様に、メインのテスト実行から 「Flakyなテスト」を削除し、その機能をカバーする手動テストを実施しましょう。
スクリーンショットを取得する
テストの実行において、スクリーンショットを取得し、失敗したテストのトラブルシューティングに役立つ詳細情報をレポートするようにしましょう。
※Ranorex(Ranorex Studio)には、テスト実行を一時停止できる「メンテナンスモード」機能があり、テスト実行中にエラーを診断して解決できます。「メンテナンスモード」機能については、以下の動画をご覧ください。
まとめ
今回の記事で紹介した方法は、メンテナンスが可能なテストケースの作成に役立ちます。アプリケーションに変更があったときに、修正が必要な既存のテストケース数を最小限に抑えることができます。また、メンテナンスが可能なテストケースを作成することは、テストの安定性を増し、デバッグを容易にします。
(この記事は、開発元 Ranorex 社 Blog 「10 Best Practices in Test Automation #3: Build Maintainable Tests」2018年5月4日の記事を元にしています。)