JenkinsからAWS DeviceFarmを使ってAndroidのInstrumentationテストを実行する


思い立ったが吉日。Jenkins上で実行しているAndroidアプリのInstrumentationテストをAWS DeviceFarm上で実行させてみる。

## AWS Device Farm PluginをJenkinsにインストール
http://docs.aws.amazon.com/ja_jp/devicefarm/latest/developerguide/continuous-integration-jenkins-plugin.html や https://github.com/jenkinsci/aws-device-farm-plugin を読むと「GitHubからcloneしてきてビルドしてできた`aws-device-farm.hpi`ファイルをインストールしてくれな」とか書いてるけど普通にJenkinsのプラグインマネージャからインストールできるのでそちらからインストールする

![20151023222632_e69edd4786acad77519f4144239b51d7413a1c23.png](https://qiita-image-store.s3.amazonaws.com/0/1742/a16bc491-5c54-0c97-c468-8853c40bb261.png "20151023222632_e69edd4786acad77519f4144239b51d7413a1c23.png")

## Device Farm用IAMユーザを作成
以下の権限をつけたユーザを作成、もしくはJenkinsを稼働させているサーバのRoleに以下の権限を付与。

```
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "DeviceFarmAll",
                "Effect": "Allow",
                "Action": [ "devicefarm:*" ],
                "Resource": [ "*" ]
            }
        ]
    }
```

`AWSDeviceFarmFullAccess`というポリシーが用意されてるのでそれをアタッチするだけで良い。
![20151023225632_6186efb0260f46805cc2c82a33b5f29ff448fcac.png](https://qiita-image-store.s3.amazonaws.com/0/1742/1c3862cd-5ca9-3adb-e9d7-e4bc21d66db9.png "20151023225632_6186efb0260f46805cc2c82a33b5f29ff448fcac.png")

## Device Farm Pluginの設定
`Jenkinsの管理` -> `システム設定`に`AWS Device Farm`の項目があるので設定。
（Jenkins稼働サーバにRoleがついている場合は設定不要、だと思う。試してない）


![20151023230429_0743fadd394b2cb906bfe2a005e780fd6d4ea4b2.png](https://qiita-image-store.s3.amazonaws.com/0/1742/b506cfd0-9e2e-1e4a-8b57-0e15dd0e3baa.png "20151023230429_0743fadd394b2cb906bfe2a005e780fd6d4ea4b2.png")

## Device Farmにプロジェクトを作成
Consoleからプロジェクトを作成する。まだTokyoには来ていないのでオレゴンに。


![20151023222646_e32176f45e9fa113eb032c0ce0d630f04115c5ad.png](https://qiita-image-store.s3.amazonaws.com/0/1742/c3637dbc-5531-27f5-7b53-9e2dc861ef8b.png "20151023222646_e32176f45e9fa113eb032c0ce0d630f04115c5ad.png")

「まずはapkをアップロードしてね！」みたいな画面になるけどJenkinsから使うことが目的なのでここからはapkのアップロードはしない。

![20151023231347_40cadbace74c9d21f40b83ce594fe05717752cbd.png](https://qiita-image-store.s3.amazonaws.com/0/1742/d6da87d0-9efa-a1dd-947a-df10d88606fc.png "20151023231347_40cadbace74c9d21f40b83ce594fe05717752cbd.png")

## Jenkinsにジョブを作成する
例としてGoogleが提供してるサンプルプロジェクト https://github.com/googlesamples/android-testing を使う。
今回はInstrumentationテストを試したいので使うのは[unit/BasicUnitAndroidTest](https://github.com/googlesamples/android-testing/tree/master/unit/BasicUnitAndroidTest)

フリースタイルプロジェクトとして作成。リポジトリを設定し
![20151024001033_d6fae358432039da16d7bca4cfbcf6bf3e2f66df.png](https://qiita-image-store.s3.amazonaws.com/0/1742/8ddd61df-9b40-cc02-c234-b997f8f9d9bf.png "20151024001033_d6fae358432039da16d7bca4cfbcf6bf3e2f66df.png")


ビルドは普通にシェルから`gradlew`をキック。
![20151024001222_70403e800e56cd3bbe4f23cec8eae52a8e942a4c.png](https://qiita-image-store.s3.amazonaws.com/0/1742/0f8d526d-a467-fa2b-50eb-e81eca1d26fe.png "20151024001222_70403e800e56cd3bbe4f23cec8eae52a8e942a4c.png")


一度そこまでで走らせて普通にビルド成功すること確認。
![20151024001331_e846a0e8e9fa5ff7d78a941dbcdcd90503d5f485.png](https://qiita-image-store.s3.amazonaws.com/0/1742/820be822-6f65-3be1-2e63-aab7dca5f5ae.png "20151024001331_e846a0e8e9fa5ff7d78a941dbcdcd90503d5f485.png")

## JenkinsのジョブにDevice Farmの処理を追加
普通にJenkinsでテストさせるだけならシェルスクリプトに

```
cd unit/BasicUnitAndroidTest

./gradlew assembleDebug
./gradlew connectedAndroidTest
```

のように`connectedAndroidTest`ジョブを追加すれば良いのだけれども、テストはDevice Farmで実行したいのでしない。
Device Farmで使うテストapkをビルドする`assembleDebugAndroidTest`タスクを追加する。

```
cd unit/BasicUnitAndroidTest

./gradlew assembleDebug
./gradlew assembleDebugAndroidTest
```

Projectは先にDevice Farmコンソール上で作成したものを選択。
Device Poolは一旦`Top Devices`にする。（Kindle Fire HDX 7, LG G Pad 7.0, Galaxy S5, Galaxy S6, Galaxy Tab 4という5つのデバイスでテストを実行する設定となっています）

実行すると、ビルド後にDevice Farmにapkをアップロードしテストを実行してくれる。

![20151024004556_2f8a2e1298548080e0ef3a870d82c583ff7c0fe0.png](https://qiita-image-store.s3.amazonaws.com/0/1742/cfc94038-57a4-6955-e06c-7d9692396dc4.png "20151024004556_2f8a2e1298548080e0ef3a870d82c583ff7c0fe0.png")

結果はJenkins上に表示されてるし、もちろんDevice Farmコンソール上では詳細も表示できる。

![20151024004745_1e5ac0f62912e3882c094f9f6ceedcd41fc44423.png](https://qiita-image-store.s3.amazonaws.com/0/1742/7cbd1a79-5d73-ec4b-a7ba-540521676ba1.png "20151024004745_1e5ac0f62912e3882c094f9f6ceedcd41fc44423.png")

なかなか簡単だし、悪くない。

## 難点
Device Farmは実機を大量に稼働させてる謎システムとのことで、テストが走り始めるまでに時間がかかることがある。
上記テストも実行ではGalaxy S5のデバイスの準備に時間がかかり全体で以下のように6分ほどかかってしまった。

```
00:39:41 [AWSDeviceFarm] Using Project 'android-app'
00:39:42 [AWSDeviceFarm] Using DevicePool 'Top Devices'
00:39:42 [AWSDeviceFarm] Using App 'unit/BasicUnitAndroidTest/app/build/outputs/apk/app-debug.apk'
00:39:42 [AWSDeviceFarm] Archiving artifact 'app-debug.apk'
00:39:42 [AWSDeviceFarm] Uploading app-debug.apk to S3
00:39:43 [AWSDeviceFarm] Waiting for upload app-debug.apk to be ready (current status: PROCESSING)
00:39:49 [AWSDeviceFarm] Upload app-debug.apk succeeded
00:39:49 [AWSDeviceFarm] Getting test to schedule.
00:39:49 [AWSDeviceFarm] Archiving artifact 'app-debug-androidTest-unaligned.apk'
00:39:49 [AWSDeviceFarm] Uploading app-debug-androidTest-unaligned.apk to S3
00:39:50 [AWSDeviceFarm] Waiting for upload app-debug-androidTest-unaligned.apk to be ready (current status: PROCESSING)
00:39:55 [AWSDeviceFarm] Upload app-debug-androidTest-unaligned.apk succeeded
00:39:55 [AWSDeviceFarm] Scheduling 'INSTRUMENTATION' run 'app-debug.apk (Jenkins)'
00:39:56 [AWSDeviceFarm] View the INSTRUMENTATION run in the AWS Device Farm Console: https://console.aws.amazon.com/devicefarm/home?#/projects/xxxxxxxxxxxxxxxxxxxx/runs/xxxxxxxxxxxxxxxxxx
00:39:56 [AWSDeviceFarm] Waiting for test run to complete.
00:39:56 [AWSDeviceFarm] Run app-debug.apk (Jenkins) status SCHEDULING
00:40:26 [AWSDeviceFarm] Run app-debug.apk (Jenkins) status RUNNING
...
00:45:58 [AWSDeviceFarm] Run app-debug.apk (Jenkins) status COMPLETED
00:45:58 [AWSDeviceFarm] Test run is complete.
```

既存のInstrumentationテストの実行環境として使うには遅いかも。Device Poolを変更してテスト対象デバイスを減らすなどすれば緩和はされるけども。
実機じゃなくていいからとても速いエミュレータとかがあると非常にありがたいのでDevice Farm側のアップデートに期待したい。

スクショ取るとかそういう機能もあるので毎日CI経由で実行してアプリの画面を記録しつづけるとかそういうのには向いてそう。

AWSなのでもちろん全部API経由で操作できるし色々使いどころはありそう。