この記事では、Androidエミュレーターを使ったUIテスト(Espresso)を分割・並列実行することによって、実行時間を短縮する方法についてわかりやすくご紹介します。
はじめに
Android アプリケーション開発において、品質を継続的に向上させるために、自動テスト・CircleCI などのCI/CDツールの導入は、もはや欠かせないものとなりました。
そして、自動テスト・CI/CDを1回導入するだけでなく、継続的に改善していくことが重要です。
例えば、アプリケーション規模や自動テストの数、開発規模が大きくなっていくと、CI/CD におけるビルド・テストの実行時間は長くなってしまい、結果として開発スピードを低下させてしまいます。
特に 今回紹介する Espresso などのUIテストでは、実際に Android 実機や Android エミュレーターを動かしてテストを実行する必要があるため、実行時間が長くなりがちです。
CircleCI では Android アプリケーション開発で、実行時間を短縮するためのさまざまな機能が揃っています。
今回は CircleCI のテスト分割・並列実行を活用して、UIテスト(Espresso)の実行時間を短縮する方法について紹介します。
まずは、CircleCIに無料で登録してこのチュートリアルを実行して行きましょう。
CircleCI を使って UIテスト(Espresso)を分割・並列実行する方法(概要)
こちらが、今回紹介する Android アプリケーションのサンプルコードです。
GitHub - tadashi0713/circleci-demo-android
複数の UIテスト(Espresso)が用意されており、実行しているテスト内容は一緒ですが、Thread.sleep() を入れることによって実行時間を変えています。
CircleCI でこのテストを実行する際には、Android Orb を使うことによって、下記のように簡潔にパイプラインを作ることが可能です。
CircleCI Developer Hub - circleci/android
android/start-emulator-and-run-tests には以下が含まれています。
- AVD(Android仮想デバイス)の作成・Androidエミュレーターの起動
- Gradle のキャッシュを利用
- UIテストを実行するための事前ビルド(./gradlew assembleDebugAndroidTest)
- Android エミュレーターが起動するまで待機
- UIテスト(Espresso)の実行(./gradlew connectedDebugAndroidTest)
この複数ある UIテスト を分割・並列実行する手順としては、以下になります。
- UIテストを実行するための事前ビルド(./gradlew assembleDebugAndroidTest)を行う
- 複数のLinux VM・ Android エミュレーターを起動する
- (実行時間に応じて) テストを分割する
- 分割されたテストを並列実行する
- 実行時間が含まれるテスト結果をアップロードする
UIテストを実行するための事前ビルドを行う
Espresso を含め、Android アプリケーションでテストを実行する際には、実行前にアプリケーションのビルドが必要になります。
今回は、後ほど複数のAndroidエミュレーターで並列でテストを実行させるために、ビルドの部分のみ(./gradlew assembleDebugAndroidTest)を事前に行います。
CircleCI のジョブ(build_for_integration_test)は以下になります。
以下の手順を行っています。
- Gradle のキャッシュを利用(Android Orb を利用)
- 事前ビルドの実行(./gradlew assembleDebugAndroidTest)
- 事前ビルドの成果物を次のジョブで利用できるようにする(persist_to_workspace)
UIテストを分割・並列実行する
事前ビルドのジョブ(build_for_integration_test)が完了したら、実際にテストを分割・並列実行するジョブ(integration_test_parallel)を実行します。
まず、並列でテストを実行するために、複数の Linux VM を立ち上げます。
parallelism を指定することで、並列で実行する Linux VM の数を増減することが可能です。
次に以下の手順を実行しています。
- 事前ビルド成果物を利用(attach_workspace)
- AVD(Android仮想デバイス)の作成・Androidエミュレーターの起動(Android Orb を利用)
- (実行時間に応じて) テストを分割、Gradle コマンドに渡すパラメーターを作成
- 分割されたテストを並列実行
- 実行時間が含まれるテスト結果をアップロード(store_test_results)
テスト分割、並列実行の部分を詳しく解説します。
UIテスト(Espresso)を実行するGradleコマンド(./gradlew connectedDebugAndroidTest)はデフォルトで全てのテストを実行します。
特定のテストを実行したい場合には、クラス名を使って以下のようなパラメーターを指定する必要があります。
実際にテストファイルを分割して、上記のパラメーターを作成している部分が以下になります。
CircleCI CLI である、circleci tests glob によって対象となるテストクラスを取得し、circleci tests split によって分割しています。
circleci tests split
には --split-by=timings
フラグを付けています。
後の store_test_results で JUnit 形式のテストレポートをアップロードしているのが確認できると思います。
--split-by=timings
フラグを有効にすることによって、テストレポートに含まれるタイミングデータを利用して均等にテストを分割しようとします。
これによって、より全体のテスト実行時間を短縮させることが可能です。
実際の並列化されたテストの実行時間については、CircleCI の UI (TIMING タブ)から見ていただくことが可能です。
実行時間の異なるテストを6並列で実行していますが、テスト実行時間にばらつきが少ないことが確認できると思います。
おわりに
この記事では、Androidエミュレーターを使ったUIテスト(Espresso)を分割・並列実行することによって、実行時間を短縮する方法について紹介しました。
今回紹介したソリューションには以下の特徴があります。
- 各テストの実行時間に応じてテストを分割・並列実行することができるため、より短時間でテスト実行を終了させることができる
- parallelism を増やすだけで、CircleCI のクラウド上で簡単に並列数をスケールさせることができる
CircleCI では、並列数による課金ではなく、1分毎の Linux VM の使用量(クレジット)によって課金されます。
今回のような複数の Linux VM を並列で実行した場合でも、コストパフォーマンスが高い形でご利用していただくことが可能です。
今後より Android アプリケーション開発のパフォーマンスを上げたい方は、是非参考にしていただければと思います。