Robotium で書いた Android アプリのテストを AWS Device Farm で実行する

ようやく AWS Device Farm を使う時間ができたので触ってみました。
仕事では、Robotium で Android アプリのテストをがっつり書いているので、Device Farm で Robotium のテストを動かす方法を記します。



# はじめに
## サンプルアプリ
Android Studio の Loading Activity のテンプレートの動作に対して、Robotium でテストを書いたサンプルアプリを [DeviceFarmSampleAndroid](https://github.com/tatsuhama/DeviceFarmSampleAndroid) に置いているので、サクッと試してみたい方はそちらをご利用下さい。
※必ず失敗するパターンを含めています。
以後はこのサンプルアプリを使って解説します。

## AWS のアカウント取得
https://aws.amazon.com/jp/getting-started/?nc2=h_l2_cc
を参考に、無料アカウントで良いので取っておいて下さい。
※Device Farm には、250 Device minute の無料枠があります。（2016/01/17現在）
https://aws.amazon.com/jp/device-farm/

# アプリのバイナリ（apk ファイル）作成
Android アプリのルートディレクトリ（`*.iml` ファイルや、`gradlew` ファイルがあるフォルダ）にて、

* `./gradlew assembleDebug` を実行して、アプリ本体の apk ファイルを作成
 *  `app/build/outputs/apk/app-debug.apk` ができていれば OK
* `./gradlew assembleAndroidTest` を実行して、テストの apk ファイルを作成
 *  `app/build/outputs/apk/app-debug-androidTest*.apk` ができていれば OK

ここで生成した、アプリ本体とテストの2つの apk ファイルを使います。
（テスト apk は、app-debug-androidTest-unaligned.apk ができていました。←で OK）

# Device Farm でテストを実行する
## プロジェクト作成
1. AWS の画面で、Device Farm を開く<br/>
　
2. `Create a new project` ボタンをクリック<br/>
![スクリーンショット 2016-01-17 20.02.36（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/81189db2-455b-b3d7-68e9-91399e148f53.png)<br/>
　
3. プロジェクト名を入力する<br/>
![スクリーンショット 2016-01-17 20.02.41（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/d87f6faf-8179-03c4-cb81-cd8be0f9d704.png)<br/>
何でも良いのですが、`DeviceFarmSampleAndroid` と入れておきました。<br/>
　
4. 作成されたプロジェクトを開く<br/>
![スクリーンショット 2016-01-17 20.03.03（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/3a867005-9973-8c6e-3608-25ea0b372681.png)<br/>
↑の `DeviceFarmSampleAndroid` をクリック<br/>
　

## テストの設定と実行

1. Create a new run<br/>
![スクリーンショット 2016-01-17 20.03.10（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/569a98b9-9f2c-84ab-8ad2-914df857c122.png)<br/>
左側のボタン（ドロイドくん / リンゴ）をクリック<br/>
　
2. 本体 apk ファイルの指定<br/>
![スクリーンショット 2016-01-17 20.03.27（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/bbc47202-e137-a764-1bc0-612ae85b126e.png)<br/>
`↑ Upload`ボタンをクリックして、本体の apk ファイル（`app/build/outputs/apk/app-debug.apk`）を指定する。<br/>
　
3. アプリケーションの情報が表示される<br/>
![スクリーンショット 2016-01-17 20.05.16（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/a3f1cd76-a2b6-c761-2fa0-632675227892.png)<br/>
`Run name` はデフォルトで入力されている。（変えたければ変更可能）<br/>
`Next step` をクリック<br/>
　
4. テストの設定<br/>
![スクリーンショット 2016-01-17 20.05.27（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/f6e08b38-376c-9ba8-9ffd-15dcafea7a65.png)<br/>
色んなテスト方法が選択できます。<br/>
（`Built-in: Fuzz`を選択すると、モンキーテストが実行されます。テストケースがない場合は、ひとまずこれでも可能）
今回は、Robotium でテストを記述しているので、`Instrumentation` を選択<br/>
　
5. テスト apk の指定<br/>
![スクリーンショット 2016-01-17 20.05.30（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/914435b1-393f-d590-8c07-0a21babea081.png)<br/>
`↑ Upload` ボタンをクリックし、テスト apk ファイル（`app/build/outputs/apk/app-debug-androidTest*.apk`）を指![スクリーンショット 2016-01-17 20.05.56（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/6152af13-f42e-fe69-33eb-e5f7849c9724.png)
![スクリーンショット 2016-01-17 20.05.56（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/95e11649-45ba-b326-341f-ed5954eb05ec.png)
定する<br/>
　
6. テストフィルタの設定<br/>
![スクリーンショット 2016-01-17 20.05.56（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/927ed8f7-d338-5606-95be-d20598bbfa49.png)<br/>
クラス指定やテストレベルの指定ができそうです（試していない）<br/>
ひとまず、デフォルトのままで `Next step` をクリック<br/>
　
7. 実行デバイスの選択<br/>
![スクリーンショット 2016-01-17 20.06.03（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/e202e105-7a30-c548-56b4-04d6d59dc97f.png)<br/>
デフォルトで、`Top Devices` が選択されています。<br/>
`Create a new device pool` で色んな機種を選択できそうです（試していない）<br/>
`Next step` をクリック<br/>
　
8. デバイス環境の設定<br/>
![スクリーンショット 2016-01-17 20.06.07（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/d922fb2c-9bef-7e45-9071-bcacf65ba073.png)
デバイス環境（他アプリ、通信環境、場所、言語、など）を必要に応じて設定できる。<br/>
デフォルトのままで、 `Review and start run` をクリック<br/>
　
9. 実行前の確認<br/>
![スクリーンショット 2016-01-17 20.06.15（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/bb9b2fc6-031d-63b9-0d89-0ea71615de9f.png)
いままでの設定を確認して、必要あれば修正できそう（試していない）<br/>
`Confirm and start run` をクリックしてテスト実行<br/>
　
10. テスト実行中…<br/>
![スクリーンショット 2016-01-17 20.06.28（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/28360050-4ed9-ba73-1b9d-1c2396f9b099.png)
この画面では全体の進捗しか確認できないので、実行中の行をクリック<br/>
　
11. テスト実行中…<br/>
![スクリーンショット 2016-01-17 20.06.41（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/a22373d9-1204-e699-9782-7714b2520781.png)
実行中の端末はぐるぐる、未実行の端末は時計アイコンが表示されています。<br/>
　
12. 実行結果１<br/>
![スクリーンショット 2016-01-17 20.11.45（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/1d42d15a-0e12-e8a4-a0c6-63254ba8fbcc.png)
必ず失敗するテスト（`LoadingActivityTestFail#testFail`）を用意しておいたので、期待通りですね！<br/>
　
13. 実行結果２（↑の下部へスクロール）<br/>
![スクリーンショット 2016-01-17 20.11.47（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/91e8bd4e-b30d-1ebd-8d4c-c14116abd9dd.png)
端末毎のテスト結果が確認できます。<br/>
端末名をクリックすると、テストの詳細が確認できます。<br/>
　
14. 実行結果３<br/>![スクリーンショット 2016-01-17 20.14.01（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/a970ecb7-cde0-3ab0-9bec-85f3c89923c8.png)
今回は、スクリーンショットを保存していないので `Screenshots` を開いてもスクリーンショットは参照できません。<br/>
`Performance` タブをクリックすると、`CPU`, `Memory`, `Threads` の値を時系列に確認できます。<br/>
![スクリーンショット 2016-01-17 21.57.17（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/70c33136-80ba-86fe-fe2d-779494582c1e.png)<br/>
　<br/>
　
`Files` タブをクリックすると、各テストでのログをダウンロードすることができます。<br/>
![スクリーンショット 2016-01-17 21.57.20（2）.png](https://qiita-image-store.s3.amazonaws.com/0/9695/9c1a1328-444f-e5ca-1724-ab82468694c9.png)<br/>

試しに、`LoadingActivityTestFail` の `Logcat` をダウンロードして見てみます。

```
（略）
01-17 03:08:25.365  8960  8973 I TestRunner: failed: testFail(jp.tokushima.tatsuhama.devicefarmsample.LoginActivityTestFail)
01-17 03:08:25.365  8960  8973 I TestRunner: ----- begin exception -----
01-17 03:08:25.365  8960  8973 I TestRunner: 
01-17 03:08:25.365  8960  8973 I TestRunner: junit.framework.AssertionFailedError: checkSearchText(This field is required)
01-17 03:08:25.365  8960  8973 I TestRunner: 	at junit.framework.Assert.fail(Assert.java:50)
01-17 03:08:25.365  8960  8973 I TestRunner: 	at junit.framework.Assert.assertTrue(Assert.java:20)
01-17 03:08:25.365  8960  8973 I TestRunner: 	at jp.tokushima.tatsuhama.devicefarmsample.UITestBase.checkSearchText(UITestBase.java:41)
01-17 03:08:25.365  8960  8973 I TestRunner: 	at jp.tokushima.tatsuhama.devicefarmsample.LoginActivityTestFail.testFail(LoginActivityTestFail.java:16)
01-17 03:08:25.365  8960  8973 I TestRunner: 	at java.lang.reflect.Method.invokeNative(Native Method)
01-17 03:08:25.365  8960  8973 I TestRunner: 	at java.lang.reflect.Method.invoke(Method.java:515)
01-17 03:08:25.365  8960  8973 I TestRunner: 	at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
01-17 03:08:25.365  8960  8973 I TestRunner: 	at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
01-17 03:08:25.365  8960  8973 I TestRunner: 	at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)
01-17 03:08:25.365  8960  8973 I TestRunner: 	at junit.framework.TestCase.runBare(TestCase.java:134)
（略）

```

`LoginActivityTestFail.java:16` で失敗したことがわかりますね。

# まとめ
Robotium で書いた Android アプリのテストコードは、本体とテストの apk を AWS Device Farm に渡してあげるだけで簡単に実行できる。<br/>

# 次やりたいこと
※次の記事の予告とは限りません

* Jenkins からビルドして自動実行
* スクリーンショットの保存と取得
* Appium や Espresso など、他の記述方法からの実行
* iOS アプリのテスト実行