AWS Device FarmでAppiumを使ったE2Eテストを動かす

# これは何？
E2EテストをAppiumと[CodeceptJS](https://codecept.io/)を使って、AndroidアプリをmacOS上のローカルで、またAWS Device Farmで実行させたときのメモです。(記載日：2020/08)  
[サンプルコード（サンプルアプリ同梱）](https://github.com/ryoyakawai/aws_device_farm_appium/tree/master/aws_devicefarm)を使うことで比較的簡単に再現できるかと思います。

# 1. E2EテストをmacOS上のローカルで実行する

## 1.1. 環境を準備する
ここ→ [appiumとCodeceptJS(node.js)を使ってAndroid & iOSのE2Eテストの実行環境構築 - Qiita](https://qiita.com/uehatsu/items/7886180ef4c0319e7748)を参考に構築しています。

### 1.1.1. appium本体とappium-doctorをインストールする
appium-doctorはappiumが正しく動作するように設定されているかをチェックするツールです。


```bash
$ npm install -g appium
$ npm install -g appium-doctor
```

### 1.1.2. appium-doctorで動作確認をする

```bash
$ appium-doctor --android
```

サンプルコードを動作させるのが目的の場合 `### Diagnostic for necessary dependencies starting ###`の項目に全てチェック（✔）が入ればOKです。
以下がappium-doctorの実行時の一例です。バツ印（✖）があるところは、インストール、設定を実行してチェック（✔）になるようにしてください。

```bash
$ appium-doctor --android
info AppiumDoctor Appium Doctor v.1.15.3
info AppiumDoctor ### Diagnostic for necessary dependencies starting ###
info AppiumDoctor  ✔ The Node.js binary was found at: /Users/ryoya/.nvm/versions/node/v14.4.0/bin/node
info AppiumDoctor  ✔ Node version is 14.4.0
info AppiumDoctor  ✔ ANDROID_HOME is set to: /Users/ryoya/Library/Android/sdk
info AppiumDoctor  ✔ JAVA_HOME is set to: /Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home
info AppiumDoctor    Checking adb, android, emulator
info AppiumDoctor      'adb' is in /Users/ryoya/Library/Android/sdk/platform-tools/adb
info AppiumDoctor      'android' is in /Users/ryoya/Library/Android/sdk/tools/android
info AppiumDoctor      'emulator' is in /Users/ryoya/Library/Android/sdk/emulator/emulator
info AppiumDoctor  ✔ adb, android, emulator exist: /Users/ryoya/Library/Android/sdk
info AppiumDoctor  ✔ Bin directory of $JAVA_HOME is set
info AppiumDoctor ### Diagnostic for necessary dependencies completed, no fix needed. ###

(....略....)

info AppiumDoctor Bye! Run appium-doctor again when all manual fixes have been applied!
info AppiumDoctor 
```

以上で環境の準備は完了です。


### 1.1.3. サンプルコードをCloneしてNPMパッケージをインストールする

```bash
$ git clone https://github.com/ryoyakawai/aws_device_farm_appium.git
$ cd uitest_sample_appium
$ npm i mocha -D && npm install
```

Cloneしたリポジトリについて。
2つのディレクトリがあります。内容は以下の通りです。

- `aws_devicefarm` : AWS Device Farm上で動作させるためのスクリプト等。詳細は「[3. E2EテストをAWS Device Farmで実行する](https://qiita.com/drafts/30d0c3e2da81b34f61bf#3-e2e%E3%83%86%E3%82%B9%E3%83%88%E3%82%92aws-device-farm%E3%81%A7%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B)」で説明します。
- `uitest_sample_appium` : AppiumとCodeceptJSを使ったサンプルのE2Eテストスクリプト。詳細は「[2. E2EテストをmacOS上のローカルで実行する](https://qiita.com/drafts/30d0c3e2da81b34f61bf#3-e2e%E3%83%86%E3%82%B9%E3%83%88%E3%82%92aws-device-farm%E3%81%A7%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B)」で説明します。

## 1.2. Appiumを実行する
コマンドからAppiumを実行するとTerminalを1つ専有しますのでTerminalは2つ起動しておくことをオススメします。

```bash
$ appium
```

## 1.3. Androidの実機を接続、または仮想マシンを起動しておく
サンプルテストがサンプルアプリをインストールしてテストを実行するAndroidのマシンになります。

### 1.3.1 デバイスの接続状況を確認する
`adb devices`を実行して以下のように、デバイスがリストとして表示されていればOKです。`emulator-5554`と`device`が一致している必要はなく、表示されれば準備完了です。以下の例はmacOS上でAndroidのエミューレータを起動したときの表示です。

```bash
$ adb devices
List of devices attached
emulator-5554	device
```

### 1.3.2. CodeceptJSの設定ファイルに実行するマシンを指定する
（ここからは`./uitest_sample_appium`以下のファイルについての説明です。）
`./uitest_sample_appium/codecept.android.conf.json`に環境に合わせて指定する項目があるので確認する。(`helpers.Appium`以下のパラメータ’の詳細は[こちら](http://appium.io/docs/en/writing-running-appium/caps/))  

確認する内容は以下の2つのパラメータ。

- `helpers.Appium.desiredCapabilities.deviceName`
- `helpers.Appium.desiredCapabilities.udid`

[デバイスの接続状況を確認する](##-デバイスの接続状況を確認する)で取得した内容に更新する。同じであれば更新は不要です。

```json
{
  "tests": "./test_cases/*_test.js",
  "output": "./output",
  "helpers": {
    "Appium": {
      "smartWait": 10000,
      "app_relative": "./lib/uitest_sample_android.apk",
      "app": "",
      "desiredCapabilities": {
        "platformName": "Android",
        "appWaitForLaunch": true,
        "deviceName": "device",
        "udid": "emulator-5554",
        "automationName": "UiAutomator2",
        "newCommandTimeout": 120,
        "appWaitDuration": 60000,
        "platformVersion": "10"
      }
    },
(....以下略....)
```

## 1.4. E2Eテストを実行する
NPMスクリプトからE2Eテストを実行する。

```bash
$ cd uitest_sample_appium
$ npm run test:android
```

## 1.5. E2Eテストの結果を確認する

[mochawesome](https://www.npmjs.com/package/mochawesome)で`./uitest_sample_appium/output/mochawesome.html`をインデックスとするHTML形式のレポートも作成されるようになっているのでブラウザで閲覧できる。

```bash:macOS
$ open output/mochawesome.html
```


# 2. E2EテストをAWS Device Farmで実行する
macOSのローカル環境で実行したE2EテストをAWS Device Farm上で実行します。

## 2.1. AWSのアカウントを準備する
必要に応じて準備してください。
必要要件はアカウントに以下のポリシーを保持していることです。

- `arn:aws:iam::aws:policy/AWSDeviceFarmFullAccess`


## 2.2. クライアントでAWSへのCLIアクセスを設定する
この辺りを参照して設定するとよいと思います。

- [AWS CLI環境設定 - Qiita](https://qiita.com/maple07/items/f5cc89ae7312ad5ac7b7)

## 2.3. AWS Device Farmの環境を設定する
1. [ここ](https://us-west-2.console.aws.amazon.com/devicefarm/home?#/projects)からプロジェクトを作成する。
![Screen Shot 2020-08-14 at 11.43.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61221/a88efcaf-3d3e-1dc0-75b0-af4d4253e059.png)

2. デバイスプール（Device Pool）を作成する。1で作成したプロジェクトのページ右上の「⚙ Project settings」のリンクでプロジェクトの設定ページに遷移する。
![Screen Shot 2020-08-14 at 11.47.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61221/d3a19731-16a0-7799-7db7-c01739319889.png)
遷移先のページで「Device pools」のタブを選択して表示する。
![Screen Shot 2020-08-14 at 11.53.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61221/218886cb-5243-231c-77c6-490f21c21a0a.png)

「Create a new device pool」を選択して、Pixel 3 XLのAndroidのOSバージョンは10を選択してデバイスプールを作成する。
![Screen Shot 2020-08-14 at 11.46.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61221/a18b21c9-4800-0f58-c2bb-836b27c4e102.png)


## 2.4. AWSへのアクセス情報を指定する
ここからは`./aws_devicefarm`以下のファイルについてお話です。

`./aws_devicefarm/scheduletest_config_devicefarm.js`
がAWS Device FarmでE2Eテストを実行する為の設定ファイル。
サンプルのテストスクリプトの実行には以下のパラメータの変更が確実に必要になる。

- `aws_access_user_arn_id`
- `aws_access_key_id`
- `aws_secret_access_key`
- `aws_devicefarm_project_arn`
- `project_name`
- `device_pool_name`

それぞれのパラメータの説明は以下の通り。

- `aws_region`
  - Device Farmを実行するAWSのRegion。（2020年8月現在は`us-west-2`のみで提供）
- `aws_access_user_arn_id` 
  - `AWSDeviceFarmFullAccess`のポリシーを保有するアカウントのIDかARN
- `aws_access_key_id`
  - `aws_access_user_arn_id`のkey ID
- `aws_secret_access_key`
  - `aws_access_user_arn_id`のAccessKey
- `aws_devicefarm_project_arn`
  - 「AWS Device Farmの環境を設定する」の1で作成したProjectのIDを指定する。
  - URLからProject IDを見つける方法。`https://us-west-2.console.aws.amazon.com/devicefarm/home?#/projects/22d13d5c-6e34-4048-xxxx-b3aadbde00bb/runs`がURLだとすると`22d13d5c-6e34-4048-xxxx-b3aadbde00bb`がProject IDとなる。
- `project_name`
  - 「AWS Device Farmの環境を設定する」の1で指定した名前。
- `device_pool_name`
  - 「AWS Device Farmの環境を設定する」の2で作成したDevice Poolの名前
- `app_file_name_path`
  - APKファイルを相対パスで指定する。 
- `test_script_file_name_path` 
  - テストスクリプトファイルのディレクトリを相対パスで指定する。
- `test_spec_file_name_path` 
  - Test Specファイル（AWS Device Farmを動作させる為のファイル）を相対パスで指定する。 

## 2.4. AWS Device Farmで実行する

```bash
$ node scheduletest_exec_devicefarm.js 
```

エラーが出ずに完了すれば、AWSのConsoleから動作を確認できるはずです。

## 2.5. E2Eテストの結果を確認する
指定したプロジェクトは以下のような表示されるはずです。
![Screen Shot 2020-08-14 at 14.15.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61221/120d0a25-c5a2-741f-69c9-e0006cb60b01.png)

1つを選択すると、テストで実行したデバイスの一覧から1つ選択をすると動画、実行の結果、ログ出力などを見ることが可能です。
また、Files > Tests の項目内の「Customer Artifacts」からはmochawesomeで作成されたHTML形式のレポートを取得することが可能です。

# コメント
E2Eテストを手軽に書きたい＆手軽に実行したい。そしてできれば開発と平行して実施したいという想いがありました。しかしながら、端末を1台E2Eのテストに費やすのもちょっと・・・と思ったときのAWS Device Farm、またはFirebase Test Labです。Firebase Test Labは[ブログ記事](https://ryoyakawai.com/blog/2019/07/03/ci-android-00.html)として書いていましたのでAWS Device Farmも試してみました。そして「E2Eテストを手軽に書く」部分もBDD（Behavior-driven development）で書けるCodeceptJSというのも導入してみました。
CodeceptJSもAWS Device Farmも情報が多いわけでないので苦戦しましたが、一旦動くとなにげに快適でしたので、もし気になったらお試しください。

# 参考サイト
- [appiumとCodeceptJS(node.js)を使ってAndroid & iOSのE2Eテストの実行環境構築 - Qiita](https://qiita.com/uehatsu/items/7886180ef4c0319e7748)