Corredor

ウェブ、プログラミングの勉強メモ。

AngularJS + Cordova なアプリに Protractor + Appium を使って iOS 実機で E2E テストを実施する方法

以前、AngularJS + Cordova なアプリに Protractor + Appium を使って iOS シミュレータで E2E テストを行う方法を紹介した。

neos21.hatenablog.com

今回はその続きで、今度は iOS 実機で E2E テストを行う方法を紹介する。

前回紹介した環境設定をしてあるのが前提になる。

実際のコードはコチラ

今回紹介したパッケージとサンプルコードを利用し、AngularJS + Cordova なアプリで Appium を使った E2E テストを行うサンプルプロジェクトを作成した。以下を参考にしてほしい。

今回の例では、Appium と Protractor の起動は、Gulp タスクとして定義している。gulpfile.js はコチラ。

WebDriver Agent の設定

プロジェクトにローカルインストールした Appium の配下にある appium-xcuitest-deriver が WebDriverAgent を抱えているので、コレの設定をする。

$ cd ./node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent/

$ sh ./Scripts/bootstrap.sh -d
-e Fetching dependencies

# XCode プロジェクトを開く
$ open ./WebDriverAgent.xcodeproj

XCode 上で以下のように設定を変更した。

  • Identity
    • Bundle Identifier
      • com.facebook.WebDriverAgentLib → 個人で適当なアプリ識別子に変更する
  • Signing
    • Team
      • None → 自分のチームを指定する
  • Status
    • エラーが出ている場合は少し上にある「Automatically manage signing」にチェックを付ける

このまま XCodeBuild をしても以下のようなメッセージが出る。

Testing failed:
Signing for "WebDriverAgentRunner" requires a development team. Select a development team in the project editor.
Code signing is required for product type 'UI Testing Bundle' in SDK 'iOS 10.3'

引き続き WebDriverAgent.xcodeproj を XCode で開き、左ペインの「TARGETS」から「WebDriverAgentRunner」を選択する。

  • General タブ
    • Signing
      • Team
        • None → 自分のチームを指定する
    • Status
      • The app ID "com.facebook.WebDriverAgentRunner" cannot be registered to your development team. と出ているはず。
  • Build Settings タブ
    • Product Bundle Identifier (右上の検索窓から検索すると楽)
      • com.facebook.WebDriverAgentRunner → 個人で適当なアプリ識別子に変更する

これで Status のエラーが消える。

iOS 実機を繋いでおき、以下のコマンドでビルドする。

$ xcodebuild -project WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination 'id=【UDID】' test

これで実機上に WebDriver がインストールされた。コンソールは「XCTRunner[893:177871] ServerURLHere->http://192.168.2.3:8100<-ServerURLHere」という表示になったらそのまま監視状態になるので Ctrl + C で終了させる。

UDID の調べ方

  1. iOS 実機を Mac に USB 接続する。
  2. iTunes を開き、「概要」画面にある「シリアル番号」部分をクリックすると「UDID」に表示が切り替わるので、右クリック → コピー でコピーする。
  3. もしくは先程インストールした「libimobiledevice」から以下のコマンドを叩くと UDID が取得できる。
$ idevice_id --list

E2E テストを開始する

以下の手順でテストを開始する。事前に iOS 実機を USB に繋いでおくこと。

  1. iOS 実機にアプリをインストールする
  2. iOS 実機に WebDriver をインストールする
  3. Appium サーバを起動する
  4. ios-webkit-debug-proxy を起動する
  5. Protractor を実行する

1. iOS 実機にアプリをインストールする

事前に iOS 実機にアプリをインストールしておく。既にインストールできている場合は飛ばして良い。

# iOS 実機向けにビルド・インストールする
$ cordova run ios

2. iOS 実機に WebDriver をインストールする

これも既にインストールできている場合は飛ばして良い。「XCTRunner[893:177871] ServerURLHere->http://192.168.2.3:8100<-ServerURLHere」のコンソール出力で止まるので Ctrl + C で抜ける。

$ xcodebuild -project ./node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination 'id=【UDID】' test

3. Appium サーバを起動する

Appium サーバを起動しておく。

# Gulp タスクからローカルインストールした Appium を起動する
$ npm run gulp appium

Appium をグローバルインストールしておき、$ appium で起動した場合は途中で WebDriver Agent のビルドが失敗して上手くいかなかった。Appium 自身の配下にある WebDriver Agent を使用しようとして、未設定のためにビルドが失敗するものと思われる。

コンフィグ設定は以下のように記述して動作したが、デフォルト設定とほとんど同じため、コンフィグ設定を指定せずとも動作するものと思われる。

/* nodeConfig.json */

{
  "configuration": {
    "cleanUpCycle": 2000,
    "timeout": 30000,
    "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
    "url": "http://127.0.0.1:4723/wd/hub",
    "host": "127.0.0.1",
    "port": 4723,
    "maxSession": 1
  }
}

4. ios-webkit-debug-proxy を起動する

Appium サーバより後に起動する。コンソールには何やらバイナリが出力される。

$ ios_webkit_debug_proxy -c 【UDID】:27753 -d

5. Protractor を実行する

iOS 実機のロックは解除しておくこと。

$ npm run gulp e2e

protractor.conf.js の設定内容を検証した結果は以下のとおり。

消したらダメだった設定項目

  • seleniumAddress: 'http://127.0.0.1:4723/wd/hub'
    • Appium サーバを認識するために必要。
  • browserName: ''
    • 必須。'Safari' などにすると Safari ブラウザが開いてしまうので、空値 '' にしておくのが慣例。
  • app: './platforms/ios/build/device/【アプリ名】.app'
  • bundleId: 【アプリ識別子】
    • appbundleId はセットで必須かつ正しく設定すること。app に記載のパスで辿れる .app と同じものが実機にインストールされていて、識別子が bundleId と一致しないと正しく動作しない。
    • 一度誤った設定で Protractor から Appium を通ると、Appium の動作がおかしくなり、再テストができなくなる。その場合は一度 Appium サーバを完全にシャットダウンし、WebDriver の再インストールからやり直すと綺麗に戻る ($ ps -A | grep appium でプロセス ID を取得し $ kill 【プロセス ID】 で確実に終了できる)。
    • ビルドのされ方によっては、app に記載のパスではなく './platforms/ios/build/emulator/ ディレクトリにビルドされてしまうことがある。その場合は実機を USB 接続した状態で $ cordova run ios より改めて実機向けにビルドすると device/ ディレクトリにビルドされる。
  • deviceName: 【iOS 実機名?】
    • 必須だが、実際の端末名と一致していなくても動作した。
    • シミュレータを使用している場合はココで 'iPhone 7' などとプラットフォーム名を指定していた。
  • udid: '【UDID】'
  • platformName: 'iOS'
  • platformVersion: '10.3'
    • udidplatformNameplatformVersion はセットで必要かつ正しく設定すること。バージョンは 10.3.1 などメンテナンスバージョンを指定しても良い (書いていても無視されるので存在しない誤ったメンテナンスバージョンを記載しても問題なし)。
    • udid は使用する検証機の UDID にする。WebDriver のビルド時に設定した UDID と一致していないといけない。
  • autoWebview: true
    • true にしないとアプリが起動したところで E2E テストがエラーになった。アプリの環境によるのかもしれない。

消して良い設定項目

  • baseUrl: ''
    • テスト中に browser.baseUrl で取得できるものになるベース URL の設定だが、iOS 向けに onPrepare() 内で browser.baseUrl を書き換えているため不要。

書かなくても影響ないが、入れておくと良いと思われる設定項目

というわけで、以下の設定が最小限の設定内容となった。

exports.config = {
  // Appium サーバの URL を指定する
  seleniumAddress: 'http://127.0.0.1:4723/wd/hub',
  
  // Capabilities to be passed to the webdriver instance.
  capabilities: {
    // 必須設定
    browserName: '',
    autoWebview: true,
    
    // テスト対象のアプリ情報
    app : './platforms/ios/build/device/【アプリ名】.app',
    bundleId: '【アプリ識別子】',
    
    // テストを実施する iOS 実機情報
    deviceName : '【iOS 実機名】',
    udid : '【UDID】',
    platformName : 'iOS',
    platformVersion: '10.3',
    
    // その他設定
    // iOS シミュレータの場合にアプリのディレクトリを削除してアプリを初期化する場合は true
    fullReset : false,
    // WebView のタイムアウト
    autoWebviewTimeout: 20000,
    // 自己証明書の確認アラートが表示されるとき自動で許可する場合は true
    autoAcceptAlerts : true
  },

// 以下略

というワケで手順まとめ

  1. iOS 実機を USB 接続する。
  2. iOS 実機にテスト対象アプリが入っていなければインストールする。
    • $ npm run run:ios
    • ./platforms/ios/build/device/【アプリ名】.app が生成されていることを確認しておくと良い。
  3. WebDriverAgent とその配下にある WebDriverAgentRunner の識別子 (Bundle Identifier) を端末ごとにユニークなモノに変更する。
    • $ open ./node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj
    • 左ペイン TARGETS : WebDriverAgentLib → General タブ → Bundle Identifier
    • 左ペイン TARGETS : WebDriverAgentRunner → Build Settings タブ → Product Bundle Identifier
    • Appium が起動する際に再ビルドするようなので、以下の手順 4. を飛ばす場合もやっておいた方が良い。
  4. iOS 実機に WebDriver が入っていなければインストールする。
    • $ xcodebuild -project ./node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination 'id=【UDID】' test
    • ServerURLHere とコンソールに出力されたら Ctrl + C で終了する。
  5. 1つ目のターミナルで Appium サーバを起動する。
    • $ npm run gulp appium
  6. 2つ目のターミナルで ios-webkit-debug-proxy を起動する。
    • $ ios_webkit_debug_proxy -c 【UDID】 -d
  7. protractor.conf.js に実機の UDID を記載する。
    • appbundleId もついでに確認しておく (iOS シミュレータの場合と設定が異なる部分なので)。
  8. 3つ目のターミナルで Protractor を実行する。
    • $ npm run gulp e2e

テスト中について

テスト中は Safari インスペクタでの参照は不可。

テストを終了する

テストを終了する際は以下の順に終了処理を行う。

  1. npm run gulp e2e でのテストが完了するまで待つか、Ctrl + C で終了させる。
  2. ios-webkit-debug-proxy を起動しているターミナルを Ctrl + C で終了させる。
  3. npm run gulp appium を起動しているターミナルを Ctrl + C で終了させる。

以上。

実践 Appium

実践 Appium