appiumとCodeceptJS(node.js)を使ってAndroid & iOSのE2Eテストの実行環境構築

# なぜこの文章を書いたか

[前回のQiita](https://qiita.com/uehatsu/items/71e584744f378b635baa)で「Vagrant + Selenium + node.js(CodeceptJS)でIE, Chrome, FirefoxのマルチブラウザE2Eテスト」について書いたのですが「どうせならスマホのE2Eテストも出来るようになりたい」と考え追加ポスト。

# 環境

OS : macOS Mojave (10.14.3)
VirtualBox : 6.0.4
Vagrant : v2.2.3
node.js : 10.15.1 (ndenvでインストール済み）
Android Studio, Xcode などはインストール済み

# インストール

## appium, appium-doctor のインストール

~~~bash
$ npm install -g appium
$ npm install -g appium-doctor
$ ndenv rehash
~~~

## appium-doctor の実行

まず実行して自分の環境に何が足りないか、設定が間違っていないかなどを確認

~~~bash
$ appium-doctor --ios --android
~~~

## 足りないものをインストール

色々と足りないのでインストール & 設定

### carthage のインストール

~~~bash
$ brew install carthage
~~~

### opencv4nodejs のインストール

~~~bash
$ brew install opencv@3
$ brew link opencv@3 --force
$ vi ~/.bash_profile
~~~

.bash_profileに以下を追加

~~~bash
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/Cellar/openssl/1.0.2q/lib/pkgconfig/"
export PATH="/usr/local/opt/opencv@3/bin:$PATH"
export LDFLAGS="$LDFLAGS -L/usr/local/opt/opencv@3/lib"
export CPPFLAGS="$CPPFLAGS -I/usr/local/opt/opencv@3/include"
~~~

~~~bash
$ exec $SHELL -l
$ OPENCV4NODEJS_DISABLE_AUTOBUILD=1 npm install -g opencv4nodejs
~~~

### ffmpeg のインストール

~~~bash
$ brew install ffmpeg
~~~

### fbsimctl のインストール

~~~bash
$ brew tap facebook/fb
$ brew install fbsimctl --HEAD
~~~

### applesimutils のインストール

~~~bash
$ brew tap wix/brew
$ brew install applesimutils --HEAD
~~~

###  idevicelocation のインストール

~~~bash
$ brew install usbmuxd libplist libimobiledevice libzip openssl make automake autoconf libtool pkg-config
$ brew list openssl
（省略）
/usr/local/Cellar/openssl/1.0.2q/lib/pkgconfig/ (3 files)
（省略）
$ vi ~/.bash_profile
~~~

.bash_profileに以下を追加

~~~bash
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/openssl/lib/pkgconfig/"
~~~

~~~bash
$ exec $SHELL -l
$ git clone https://github.com/JonGabilondoAngulo/idevicelocation.git
$ cd idevicelocation
$ ./autogen.sh
$ make
$ sudo make install
~~~

### ios-deploy のインストール

~~~bash
$ npm install -g ios-deploy
~~~

### ios-webkit-debug-proxy のインストール

~~~bash
$ brew install ios-webkit-debug-proxy
~~~

### JAVA_HOMEの設定

~~~bash
$ vi ~/.bash_profile
~~~

.bash_profileに以下を追加

~~~bash
export JAVA_HOME=`/usr/libexec/java_home -v 10`
export PATH="$PATH:$JAVA_HOME/bin/"
~~~

~~~bash
$ exec $SHELL -l
~~~

### bundletool.jar のインストール

~~~bash
$ mkdir ~/bin/
$ cd ~/bin/
$ wget https://github.com/google/bundletool/releases/download/0.8.0/bundletool-all-0.8.0.jar
$ ln -s bundletool-all-0.8.0.jar bundletool.jar
$ chmod a+x bundletool-all-0.8.0.jar
$ vi ~/.bash_profile
~~~

.bash_profileに以下を追加

~~~bash
export PATH="$PATH:$HOME/bin/"
~~~

~~~bash
$ exec $SHELL -l
~~~

## 再度 appium-doctor の実行

~~~bash
$ appium-doctor --ios --android
（前略）
info AppiumDoctor
info AppiumDoctor Everything looks good, bye!
info AppiumDoctor
~~~

`Everything looks good, bye!` と出ていれば問題無し

## ChromeDriver のインストール
AndroidのChromeを動作させるためにChromeDriverをインストールする
Android 9.0のChromeのバージョンに合わせて、ここではChromeDriverのバージョンをv2.44としています

詳細：
https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/web/chromedriver.md
http://chromedriver.chromium.org/downloads

~~~bash
$ wget https://chromedriver.storage.googleapis.com/2.44/chromedriver_mac64.zip
$ unzip chromedriver_mac64.zip
$ mv chromedriver ~/bin/chromedriver_v2_44
~~~

# npmを使ってテスト環境の構築

普通にディレクトリを作ってテスト環境を構築する

## npm init 他

~~~bash
$ mkdir sptest
$ cd sptest
$ npm init -y
$ npm install codeceptjs --save-dev
~~~

## codecept.jsの初期化

~~~bash
$ npx codeceptjs init

  Welcome to CodeceptJS initialization tool
  It will prepare and configure a test environment for you

Installing to /Users/xxxx/sptest
? Where are your tests located? ./*_test.js
? What helpers do you want to use? Appium
? Where should logs, screenshots, and reports to be stored? ./output
? Would you like to extend I object with custom steps? Yes
? Do you want to choose localization for tests? ja-JP
? Where would you like to place custom steps? ./steps_file.js
Configure helpers...
? [Appium] Application package. Path to file or url http://localhost
? [Appium] Mobile Platform iOS
? [Appium] Device to run tests on emulator
Steps file created at /Users/xxxx/sptest/steps_file.js
Config created at /Users/xxxx/sptest/codecept.conf.js
Directory for temporary output files created at `_output`
Almost done! Create your first test by executing `codeceptjs gt` (generate test) command

--
Please install dependent packages locally: npm install --save-dev webdriverio@^5.2.2
$ npm install --save-dev webdriverio@^5.2.2
~~~

# 実際のテスト

## appiumの起動

~~~bash
$ appium --chromedriver-executable ~/bin/chromedriver_v2_44
~~~

## テストの記述

前回と同じ、github.comに行って、"GitHub"という文字列があるかどうかをチェックするだけのコードを書きます。

github_test.js

~~~javascript
Feature('Github');

Scenario('test something', (I) => {
  I.amOnPage('https://github.com');
  I.see('GitHub');
});
~~~

## iOS用の設定ファイルを作成

自動で作成されてますが、それを以下のようにいじります。

codecept.ios.conf.js

~~~javascript
exports.config = {
  tests: './*_test.js',
  output: './output',
  helpers: {
    Appium: {
      platform: "IOS",
      desiredCapabilities: {
        "platformName": "iOS",
        "platformVersion": "12.1",
        "deviceName": "iPhone 7",
        "automationName": "XCUITest",
        "browserName": "Safari"
      }
    },
  },
  include: {
    I: './steps_file.js'
  },
  bootstrap: null,
  mocha: {},
  name: 'test',
  translation: 'ja-JP'
}
~~~

## Android用の設定ファイルを作成

同様にAndroid用も

~~~javascript
exports.config = {
  tests: './*_test.js',
  output: './output',
  helpers: {
    Appium: {
      platform: "Android",
      desiredCapabilities: {
        automationName: "Appium",
        deviceName: "Nexus 5x API 28 for appium",
        platformVersion: "9",
        browserName: "Chrome"
      }
    },
  },
  include: {
    I: './steps_file.js'
  },
  bootstrap: null,
  mocha: {},
  name: 'test',
  translation: 'ja-JP'
}
~~~

# テスト実行

iOSにしろAndroidにしろ、問題があればappiumを起動しているターミナルに何かしらエラーが出ているので解読して下さい

## iOS

以下のコマンドを実行すると、初回時に必要な設定を自動でしてくれた上でSafariが起動してテストが実行されます

~~~bash
$ npx codeceptjs run --steps --config=./codecept.ios.conf.js
~~~

## Android

以下のコマンド実行の前にAndroid StudioからAndroidエミュレータを立ち上げておきます

Name : Nexus 5x API 28 for appium
OS : Pi (Android 9.0)

~~~bash
$ npx codeceptjs run --steps --config=./codecept.android.conf.js
~~~

## npm runで実行できるように package.json を修正

package.json

~~~javascript
{
  "name": "sptest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "npm run test:ios; npm run test:android",
    "test:ios": "codeceptjs run --steps --config=./codecept.ios.conf.js",
    "test:android": "codeceptjs run --steps --config=./codecept.android.conf.js"

  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "codeceptjs": "^2.0.7",
    "webdriverio": "^5.7.1"
  }
}
~~~

### iOS

~~~bash
$ npm run test:ios
~~~

### Android

~~~bash
$ npm run test:android
~~~

### iOSとAndroidの逐次実行

~~~bash
$ npm run test
~~~

# 終わりに

これで前回のSelleniumと合わせて、ブラウザテストが一通り出来るようになったので、これを使ってガリガリE2Eテスト書いていきます