読者です 読者をやめる 読者になる 読者になる

Firebase Test Labを使ったAndroidアプリのテスト

Androidエンジニアの堀江(@Horie1024)です。Androidアプリのテストについて考えた時、UIの操作を含むActivity単位の結合テストをどう実行するか?が課題になります。

最近では、テスト基盤をクラウド上で提供するサービスが複数リリースされており、今年のGoogle I/Oで正式に公開されたFirebase Test Labもその一つです。本記事では、Firebase Test LabでのAndroidアプリのテストについてご紹介しようと思います。

f:id:vasilyjp:20160930113931p:plain

サンプルアプリ

本記事を通してサンプルアプリとして以下を使用します。2Activityで構成される簡単なアプリで、テストコードをEspressoで書いています。

github.com

Firebase Test Labとは?

以下の動画を観ていただければ概要は掴めるかと思います。

Firebase Test LabはGoogleが提供しているクラウドベースのAndroidアプリのテスト基盤です。以前はCloud Test Labと呼ばれていましたが、Google I/O 2016でFirebaseの一機能として正式にリリースされました。「for Android」と紹介されていますが、iOS版は(今のところ)ありません。

Firebase Test Labの特徴としては以下の3点が挙げられます。

  • 実機でのテスト
    • Googleのデータセンターに配置された実機でテストが実行される。デバイスの種類、OSのバージョン、Localeなどの組み合わせた幅広い条件でのテストをまとめて実行でき、特定の条件での不具合を発見しやすくなる。
  • テストコード不要なテスト
    • Roboテストと呼ばれるテストの実行モードがあり、テストコード無しでアプリのテストを実行可能。テストコードがあるのであれば、それをFirebase Test Labで実行可能。
  • 開発フローへの統合
    • Android Studio、Firebase console、gcloudコマンドからテストを実行可能。gcloudコマンドを使用することでJenkinsやCircleCIといったCIシステムとの連携も可能。

Firebase Test Labでのテストの概要

テスト手法

Test Labで選択できるテスト手法は以下の2種類です。

  • Instrumentationテスト
  • Roboテスト

Instrumentationテスト

Instrumentationテストで使用できるテスティングフレームワークは以下の3種類となっており、実機で30分、仮想端末で60分以内に完了したテストについてのみ結果を取得できます。

Roboテスト

Roboテストは、Instrumentationテストのテストコードを書いていない場合でも、クローラーの様にアプリのUI構造を解析し探索することで、自動的にユーザーの操作をシミュレートすることでアプリの不具合を発見します。詳細の後ほど紹介します。

テストの実行方法

テストの実行方法は、3種類から選択可能です。

  • Firebase console
    • Web UIによってAPKのアップロードとテストの実行があらゆる環境で可能
  • Android Studio
    • 開発環境から開発中のアプリのテスト実行が可能
  • CLI
    • gcloudコマンドによってCLIからの実行が可能になり、自動ビルドおよび自動テストプロセスへの組込みが可能

また、これら3つの方法とは別にpre-launch reportsという機能があり、これによってAPKをPlay Storeにα or βでアップロードした際に苞を自動で実行させることができます。pre-launch reportsの詳細は後ほど紹介します。

テストが実行される条件について

Firebase Test Labでは作成したTest Matrixに従ってテストが実行されます。Test Matrixは、Test DimensionTest Executionと呼ばれる概念から決定されています。

Test Dimensionは、デバイスに関連する設定項目のことで、各Dimensionはデバイスタイプ、APIレベル、ロケール、画面の向きからなります。テストを実行する前に各Dimensionから項目を選択することでFirebase Test Labが有効な設定項目の組合せのリストを生成します。各有効なDimensionの組合せをTest Executionと呼びます。そして、Test ExecutionのリストがTest Matrixであり、選択したTest Dimensionの組合せです。

まとめると以下のようになります。

名称 概要
Test Dimension デバイスに関連する設定項目
Test Execution 有効なTest Dimensionの項目の組合せ
Test Matrix Test Executionのリスト

例として次のような条件をTest DimensionとしてTest Labに与えた場合を考えてみます。

  • デバイス: Nexus 5, Nexus 6
  • APIレベル: 21, 22
  • ロケール: Japanese
  • 画面の向き: 縦向き

この条件から得られるTest Matrixは以下のようになります。

デバイス APIレベル ロケール 画面の向き
Nexus 5 21 Japanese 縦向き
Nexus 5 22 Japanese 縦向き
Nexus 6 21 Japanese 縦向き
Nexus 6 22 Japanese 縦向き

この時選択した端末とAPIレベルによっては無効な組合せとなる場合がり、その場合テストの実行はスキップされます。また、Test Matrixの各Test Executionはpassかfailのいずれかの結果になり、もしTest Executionが1つでもfailならば、テスト全体がfailになります。

料金体系

Test Labを利用するには、FirebaseのBlazeプランを契約する必要があります。そして、利用料金は以下の通りです(2016/9/30現在)。

  • 各実機に対して $5/1時間
  • 各仮想端末に対して $1/1時間(2016/10/1まで無料)

課金処理は、分単位でされ、テストを実行するために使用した時間分のみ課金されます。アプリのインストールに掛かる時間やテスト結果を集計する時間は含まれません。

Firebaseプロジェクトの作成と課金

Firebaseプロジェクトの作成

Firebaseのプロジェクトをまだ作成していないのであればFirebase consoleから作成します。「新規プロジェクトを作成」をクリックし、プロジェクト名と国を選択し、「プロジェクトを作成」をクリックします。これでプロジェクトが作成されます。

f:id:vasilyjp:20160930014125p:plain

課金

作成したプロジェクトのメニューから「Test Lab」を選択します。

f:id:vasilyjp:20160930014246p:plain

Test Labを利用するためには、「Blazeプラン」を選択する必要があるので選択します。

f:id:vasilyjp:20160930014306p:plain

課金処理が完了すると以下のような画面になり、これでFirebase Test Labを利用する準備ができました。

f:id:vasilyjp:20160930014323p:plain

テストの実行

前節まででFirebase Test Labを利用する準備ができたので、実際にテストを実行してみましょう。「最初のテストを実行する」をクリックすると以下のウィザード画面が表示されます。

f:id:vasilyjp:20160930014948p:plain

テスト手法として「Roboテスト」、「Instrumentationテスト」の2種類から選択できます。その他のテスト方法として「gcloud」、「Android Studio」の2種類が紹介されていますが、これらは後ほど紹介します。

Roboテスト

Roboテストとは、Firebase Test Labにデフォルトで組込まれているテストツールです。Roboテストは、クローラーの様にアプリのUI構造を解析し探索することで、自動的にユーザーの操作をシミュレートします。Monkey testとは異なり、Roboテストでは、シミュレートするユーザーの操作(種類や順番)は、デバイスの設定などの条件が同じならば常に一定になります。

この特徴によって、Roboテストは、Monkey testでは不可能なバグフィックスの確認やリグレッションテストに利用できます。また、シミュレートしたユーザーの操作は、ログ、スクリーンショット、スクリーンショットから生成した動画によって確認でき、クラッシュの原因を把握するための手がかりとなります。

Roboテストで使われる用語について

Roboテストのドキュメントで使用されている用語についてまとめます。

  • Root
    • メインスクリーン
  • UI Branch
    • 枝分かれした画面遷移の分岐
  • Depth
    • 画面の階層の深さ

画面A-Eまで存在し、A->B、A->C、B->D、B->Eと画面遷移する場合、以下のような図になります。

f:id:vasilyjp:20160930015059p:plain

Roboテストの設定

Maximum depth

RoboテストがアプリのUI階層のどの程度の深さまで探索するかをMaximum depthによって設定できます。Maximum depthは、テストが特定のUI BranchからRootに戻るまでどの程度の深さまで探索すべきかを指定します。デフォルト値は50です。値を2未満に指定すると探索はRootで止まります。

Timeout

Roboテストの実行時間についてTimeoutを指定できます。アプリのUIの複雑さによってRoboテストが完了するまでに時間は変化します。推奨設定値は、通常のアプリで120秒、複雑なUIを持つアプリで300秒です。デフォルト値は、Android StudioやFirebase consoleから実行した場合300秒、gcloudツールから実行した場合1500秒となっています。

パラメータ設定についての補足

公式ドキュメントには、画面の分岐が多く、遷移の深さが深い場合、Roboテストがアプリを完全に探索できるよう以下の設定のうちいずれかを検討するべきであると書かれています。

  • timeoutを高い値に設定し、Roboテストが複数のUI Branchを探索できるようにする
  • maximum depthを低い値に設定し、Roboテストに各UI Branchの探索を完了させる

パラメータの設定については、アプリによって適切な値が異なるため、最初はデフォルト値で運用しその後パラメータを調整するのが良さそうです。

Google Play Developer Consoleとの連携

Pre-launch reportsという機能がFirebase Test Labリリース後から利用できるようになっています。この機能は、APKをalphaもしくはbetaでGoogle Play Developer Consoleにアップロードした際に自動的にRoboテストを実行する機能です。テストには、Googleが一般的によく使われていると判断した複数のデバイスで、OSのバージョンやlocationなどの設定が異なる複数の条件で実行されます。ただ、世界でよく使われている端末が選択されているようで日本製の端末は含まれていませんでした。

この機能を有効にする方法はこちらにまとまっています。Pre-launch reportsは無料で使用できます。Blazeプランを契約している場合、Roboテストの代わりに任意のテストを実行可能です。

以下は、iQONでPre-launch reportを有効にした際にRoboテストが実行された端末のリストです。

f:id:vasilyjp:20160930015221p:plain

テスト結果は各端末毎に確認できるようになっています。

f:id:vasilyjp:20160930015235p:plain

Roboテストの制限

Roboテストには、テストを実行する上での制限が3つ存在しています。

  1. UI framework support
  2. Sign-in
  3. Scripting

UI framework support

Roboテストは、Android UI frameworkの要素(View、ViewGroupオブジェクトなど)が使用されたアプリにのみ対応しています。もしUnityのような別のUI frameworkを利用している場合、テストは何も実行されずRootから進まずに終了します。

Sign-in

Roboテストは、サインイン画面を迂回できません。唯一サインイン画面を迂回できる例は、認証にGoogleアカウントを使用しかつ追加のアクション(ユーザー名を入力するような)を要求しない場合です。

以下は、Roboテストのテスト結果で確認できるアクティビティマップという図になります。RoboテストはiQONへのログインを試みていますが、ログイン、新規登録画面から先にRoboテストが進むことができていません。

f:id:vasilyjp:20160930015333p:plain

解決方法として考えられるのは、System PropertyでTest Labでアプリが実行中であることを判別し、その場合に認証をスキップする方法です。Settings.System.getStringメソッドでfirebase.test.labを参照することでTest Labでアプリが実行中かを判別できます。

String testLabSetting =
  Settings.System.getString(context.getContentResolver(), "firebase.test.lab");
  if ("true".equals(testLabSetting)) {
    // Test Labでの実行中に行う処理
  }

Scripting

Roboテストでは、スクリプトを書いて任意の操作を行わせることはできません。アプリに対して行われる操作は全てTest Lab側で決定されます。

Roboテストの実行

「Roboテストを実行」をクリックすると以下の画面になるのでAPKをアップロードし、完了後に「続行」をクリックします。

f:id:vasilyjp:20160930015416p:plain

ディメンションを選択という画面に遷移します。ここでは、Roboテストを実行する端末の種類やAPIレベルといったTest Dimensionを指定します。

f:id:vasilyjp:20160930015455p:plain

詳細設定からタイムアウト(Timeout)と最大深度(Maximum depth)を指定可能です。

f:id:vasilyjp:20160930015532p:plain

下部にある「X件のテストを開始」をクリックすることでテストを開始します。先程指定したTest DimensionをもとにTest Matrixが作成され、Test LabはそのTest Matrixに従ってテストを実行します。

f:id:vasilyjp:20160930015605p:plain

Instrumentationテスト

基本的にRoboテスト場合と同様の手順になります。InstrumentationテストがRoboテストと異なるのは。通常のAPKとは別にテストAPKが必要になる点です。以下の様に「アプリAPK」と「テストAPK」をアップロードする必要があります。

f:id:vasilyjp:20160930015646p:plain

テストAPKは以下のコマンドで作成できます。

$ ./gradlew assembleDebugTest

次にRoboテスト同様Test Dimensionを指定します。

f:id:vasilyjp:20160930020018p:plain

そして、下部にある「X件のテストを開始」をクリックすることで、こちらもRoboテスト同様テストを開始します。

f:id:vasilyjp:20160930020055p:plain

テスト結果の確認

テスト結果はアプリ毎にグルーピングされ過去のものも含めてFirebase consoleのTest Labタブから確認でき、テスト実行後90日間保存されます。

f:id:vasilyjp:20160930020130p:plain

テスト結果は各Test Execution毎に表示されたアイコンで簡単に判別できます。

アイコン 意味
f:id:vasilyjp:20160930020157p:plain 成功
f:id:vasilyjp:20160930020211p:plain 1件以上失敗
f:id:vasilyjp:20160930020227p:plain Test Labのエラーにより実行不能
f:id:vasilyjp:20160930020238p:plain スキップ

さらに、各Test Execution毎に詳しいテスト結果を確認できます。Instrumentationテストでは、テストケース、ログ、スクリーンショット、動画でテスト結果を確認できます。また、「ソースファイルを表示」をクリックするとCloud Storageへアクセスでき、元データを確認できます。

f:id:vasilyjp:20160930020424p:plain

Roboテストでは、テストケースの代わりにアクティビティマップが表示されます。

f:id:vasilyjp:20160930020458p:plain

Android Studioからの実行

Firebase Test Labでのテストは、Android Studioからも実行できます。実行出来るようにするには、Android StudioのTest Configurationを設定する必要があります。以下は、Android Studioの設定からテストを実行するまでの手順です。

  1. メインメニューから「Run」> 「Edit Configurations」をクリックします。
  2. Add New Configuration「+」をクリックしAndroid Testsを選択します。 f:id:vasilyjp:20160930020536p:plain
  3. Android Testのconfigurationダイアログが開いたら
    1. Test name、Module type、Test type、Test classを設定します。
    2. Targetのドロップダウンから「Firebase Test Lab Device Matrix」を選択します。
    3. Firebaseと未接続なら「Connect to Firebase」をクリックしログインします。 f:id:vasilyjp:20160930020712p:plain
    4. 以下の赤枠で囲ったボタンをクリックし、Firebaseプロジェクトを選択します。 f:id:vasilyjp:20160930020746p:plain
  4. Test Matrixの作成と設定
    1. Matrix Configurationの以下の赤枠で囲ったボタンをクリックしダイアログを開きます。 f:id:vasilyjp:20160930020818p:plain
    2. Add New Configuration (+)をクリックします。
    3. Name欄にConfigurationの名前を記入します。
    4. テストを実行したいDevice、Platform、Locale、Orientationにチェックを入れます。
    5. OKをクリックし保存します。 f:id:vasilyjp:20160930020856p:plain
  5. Run/Debug ConfigurationsダイアログのOKをクリックし閉じます。

これでAndroid StudioからFirebase Test Labでのテストを実行できるようになったので、作成したConfigurationを選択してRunボタンをクリックしテストを実行することができます。テストの実行結果は以下のように表示されます。また、Firebase consoleでテスト結果の詳細を確認することも可能です。

f:id:vasilyjp:20160930020926p:plain

CLIからの実行

Firebase Test Labは、gcloudコマンドを使用してCLIからテストの実行をスケジューリング可能です。CLIでの実行は以下のQiitaの記事としてまとめています。

qiita.com

CIシステムとの連携

CIシステムからFirebase Test Labのテストを実行することも可能です。CircleCIを例にCIシステムとFirebase Test Labの連携については以下のQiitaの記事としてまとめています。

qiita.com

まとめ

Firebase Test Labの概要と使用方法についてご紹介しました。Roboテストでの認証処理や、日本製端末が選択出来ないなどの問題はありますが、比較的簡単にテストを実行することができます。先日リリースされたAndroid Studio 2.2では、Espresso Test Recorderが搭載されるなどEspressoでテストを書くハードルは下がっていますし、Firebase Test Labと併せることでUIのテストを実行しやすくなるはずです。弊社でもiQONの開発フローに導入していこうと思います。

最後に

VASILYではiQONを一緒に開発してくれるAndroidエンジニアを募集しています。ご興味がある方は以下のリンクをご覧ください。