機械学習自動テストツール「Magic Pod」を使ってみよう(サンプルアプリを通じたワークフロー体験編)
※この記事は古くなっていて、現在のMagic Podの機能とは異なる部分がたくさんあります。
こんにちは、戸田です。
みなさんMagic Podしてますか?
アサーションも待機処理もできるなら、もう大概のアプリのテストは作れますよね!
えっ、まだしてない?
そうですね、実際に自分の仕事で使えるのか、不安だとなかなか使えませんよね。
では、もうちょっと実際のプロジェクトで起こりそうなワークフローを、iOS向けアプリのサンプルプロジェクトを通じて実践してみましょう。
今回のサンプルプロジェクトで想定しているのは、映える写真をインスタントに共有できるiOS向けアプリ「PhotoApp」の開発中の状態です。このアプリは、ログインすると写真の一覧が見られて、写真をタップすると詳細が見られます。既にデバッグビルドは通っていて、シミュレーターで動作確認できるようになっている状態とします。
Magic Pod テストケースの作成
では、このアプリのテストケースをMagic Podで作ってみましょう。
まず、テスト対象を設定します。今回は、iOS 11.1のiPhone 7のシミュレーターを使います。みなさんは、ご自分のお手元の環境に適したものをご設定ください。
ここで、ビルド済みのAppファイルの絶対パスを指定しましょう。Xcodeでは、プロジェクトナビゲーターの「Products」の中にあるAppファイルを選択すると、ファイルインスペクターの「Full Path」にAppファイルの絶対パスが表示されますので、これを転記してください。
設定が完了したら、シミュレーターに接続しましょう。Magic Pod Desktopのコンソールに「Connected to the device」と表示されたら、接続完了です。
では、サクサクと画面をキャプチャして、対応するテストケースを作っていきましょう。今回は、ログイン後に一覧画面で表示されている日付と、その先の詳細画面で表示されている日付が一致しているかを確認するテストを作ります。
まず、ログイン画面です。同じログイン画面ですが、テキストフィールドに入力するときに画面が全体的に上に移動する仕掛けがあって見た目の構造が大きく変わりますので、念のため2種類の画面ととらえてテストケースを作りましょう。
次に、一覧画面です。ここでは、表示されている日付の文字列を、次の画面の日付文字列との比較のためにいったん変数に保存しておきます。
最後に、詳細画面です。先ほど保存した変数を呼び出して、この画面に表示されている日付と比較します。
ここでテストケースの作成はいったん完了です。実行して、成功することを確認してみましょう。
アプリへの機能追加と、対応するテスト項目の追加
さて、実際のアプリ開発プロジェクトでは、開発とテストが1回きりで済むことはあまり無く、リリースした後も不具合を修正したり新しい機能を追加したりしますし、それにともなって既存のテストのやり直しだけでなく、新しいテストを追加する必要も出てきます。
Magic Podでこのような状況に対応する場合は、変更が入った画面を再度キャプチャして、変更に対応する新しいテスト項目を追加します。
ここでは、先ほどのアプリに「お気に入り」機能が追加された想定で、一覧画面と詳細画面のお気に入り表示についてのテストを追加していきましょう。
画面右下の、既存の画面キャプチャを選択するボタンをクリックして、既存の画面キャプチャの一覧を表示させます。
変更が入ったので再キャプチャしたい画面にマウスオーバーすると、画面の右下に再キャプチャボタンが表示されますので、クリックします。
再キャプチャが完了した後、既存の画像を上書きして問題ないか確認ダイアログが表示されます。問題なければ「OK」をクリックします。
では、一覧画面と詳細画面を再キャプチャして、新しいテストケースを挿入してみましょう。ここでは、日付文字列の比較と同様に、お気に入りの表示を比較します。
まず、一覧画面でお気に入りの表示内容を変数に保存して...
詳細画面で、先ほど保存した変数を呼び出して、この画面のお気に入りの表示と比較します。
では、テストを実行してみましょう。
...おや?失敗してしまいましたね。
なぜ失敗したか見てみますと、一覧画面の表示は「79 favs」、詳細画面の表示は「79 Favs」と、英字の大小が微妙に統一されていなかったのでした。開発した人は、うっかりしてましたね。アプリ側を修正して、テストを再度実行しましょう。
...成功しましたね!
CIサービスと連携した継続的なテスト
さて、実際のプロジェクトでの利用を考えますと、ここまで作ったMagic Podのテストケースを、既存のCI(Continuous Integration)プロセスに組みこんで継続的にテストしていくにはどうしたらいいかが気になるところですね。
ここまで、Magic Pod Desktopを使ったGUI上でのテスト実行のやり方を説明してきましたが、Magic Podで一度作ったテストケースはCLIのコマンドでも実行できますので、CIサービスにかんたんに組み込めます。実際に試してみましょう。
Magic PodのWeb APIからの実行(新しいやり方)
Magic PodのWeb APIに、curlコマンド(Mac/Linux)やInvoke-RestMethodコマンド(Windows PowerShell)などからアクセスすることで、Magic PodをCLIで操作することができます。詳しくはヘルプページをご覧ください。
コマンドラインからのテスト一括実行 (クラウド・外部クラウドサービス)
Magic Pod DesktopのCLIでの実行(古いやり方)
Magic Pod DesktopのCLIでの実行コマンドはごくかんたんです。実行する前に、次の点が必要になりますのでご注意ください。
- 起動中のMagic Pod Desktopアプリを終了しておきます。
- Magic Pod Desktopアプリがあるディレクトリに、あらかじめ移動しておきます。
- --magic-pod-config オプションによる設定ファイルの指定が必須ですので、作成しておきます。
$ cd [Magic Pod Desktopアプリがあるディレクトリ] $ "Magic Pod Desktop.app/Contents/MacOS/Magic Pod Desktop" run \ --magic_pod_config=[設定ファイル(JSON形式)のフルパス]
設定ファイルはMagic Pod DesktopアプリをGUI実行しているときに自動生成されていて、 /Users/[ユーザー名]/Library/Application Support/magic_pod_desktop/magic_pod_config.json に保存されています。これを雛形として流用しましょう。
例えば、前述のiOSアプリのテストケース向けの設定ファイルは次のようになります。
{ "owner": "ATeam", "project": "MyIOSApp", "capabilities": { "platformName": "iOS", "platformVersion": "11.1", "deviceName": "iPhone 7", "automationName": "XCUITest", "app": "/Users/hiroshitoda/Library/Developer/Xcode/DerivedData/PhotoApp-gjkitmhmorcxmlfogrreldovolwq/Build/Products/Debug-iphonesimulator/PhotoApp.app", "noReset": true }, "xmlTestOutput": true, "externalAppium": false, "debug": false, "serverUrl": "https://magic-pod.com", "workDir": "/Users/hiroshitoda/magicPod", "testNumber": "1", "envVars": [], "appiumServerUrl": "", "sendMail": false }
xmlTestOutput を true にしておきますと、実行後にJUnit形式のテスト結果ファイル(XML形式)が workDir で指定したディレクトリに出力されます。他のツールでテスト結果を集計したい時に利用しましょう。
CLIで実行した結果は、Magic Pod上ではプロジェクト画面の「バッチテスト実行」ページで確認できます。
Travis CIでの実行例
iOSアプリをビルドできる環境であればどこでも、先ほどの実行コマンドを使ってMagic Podテストケースを実行できます。
この記事では、CIサービスでの実行例として Travis CI 向けの設定と CircleCI 向けの設定をご紹介します。
最初は、Travis CI向けの設定です。
まず、iOSアプリのビルドをCLIから実行できるように、プロジェクト設定を変更しましょう。Xcodeのメニューで、「Product」→「Scheme」→「Manage Schemes」を選択します。
Schemeの管理画面になります。「Shared」にチェックをつけて、「Close」ボタンをクリックしてください。
このプロジェクト設定と対応する項目を、Travis CIの設定ファイル .travis.yml に書き加えてみましょう。 xcode_scheme に、先ほどチェックをつけたSchemeの名前を記載します。
language: swift os: osx osx_image: xcode9.2 xcode_project: PhotoApp.xcodeproj xcode_scheme: PhotoApp
CocoaPods により何か依存ライブラリを利用されている場合は、 キャッシュ設定を入れておくと良いでしょう。
cache: cocoapods
次に、appファイルをビルドする設定です。がんばって xcodebuild コマンドと長大なオプションを書き上げても良いですが、ここではCIサービスでも標準的に利用できる fastlane を使って簡潔に設定していきましょう。
fastlane scan コマンドで、シミュレーター向けのビルドと単体テストがまとめて実行されます。ビルドターゲットとなる機器・OSは SCAN_DEVICE 、Schemeは SCAN_SCHEME で設定します。また、appファイルの出力先を固定するために SCAN_DERIVED_DATA_PATH も設定して、 magic_pod_config.json ファイルの app の設定と整合するようにしましょう。
script: - export SCAN_DEVICE="iPhone 7 (11.1)" - export SCAN_SCHEME=PhotoApp - export SCAN_DERIVED_DATA_PATH=$(pwd)/DerivedData - fastlane scan
なお、もしもビルドターゲットとなる機器・OSを上記のとおりにうまく利用できない場合は、プロジェクトのターゲットバージョン設定を見て、CIサービスが提供している環境と合致しているか確認しましょう。
iOSプロジェクトには、ターゲットバージョンを設定するところが2つあります。まず、「General」タブの「Deployment Info」セクションの中、「Deployment Target」を確認・設定しましょう。
次に、「Build Settings」タブの「Deployment」セクションの中、「iOS Deployment Target」を確認・設定しましょう。
これらのプロジェクト設定はデフォルトでは空欄になっている場合もありますが、必ず明示的に設定してください。
ビルドの次は、Magic Pod Desktopの設定です。動作確認ができているバージョンのファイルをダウンロードして利用するようにしましょう。
- if [ ! -e MagicPodDesktop*.*.*.zip ]; then curl -L -O "MagicPodDesktop.zipのダウンロードURL"; unzip -q MagicPodDesktop*.*.*.zip; fi
当然ながら、Magic Pod Desktopはダウンロードしただけでは自分のアカウント情報が無いため利用できません。認証済みの環境(例えば、あなたがご利用中のPC)にはホームディレクトリにセキュリティトークン .magic_pod_token が保存されていますので、この内容を利用します。非常に重要な情報ですので、Gitリポジトリなどに保存したりしてうっかり露呈しないようにしましょう。
Travis CIではリポジトリ設定の「Environment Variables」に、ログ等には出力されない環境変数を設定できます。ここに設定したうえで、実行時に環境変数の内容をファイルに書き出すように設定しましょう。
- echo -n ${magic_pod_token} > ~/.magic_pod_token
最後に、Magic Pod Desktopの実行コマンドです。
- Magic\ Pod\ Desktop.app/Contents/MacOS/Magic\ Pod\ Desktop run --magic_pod_config=$(pwd)/magic_pod_config.json
ここまで断片的に記載しました .travis.yml をまとめますと、次のようになります。
language: swift os: osx osx_image: xcode9.2 cache: cocoapods xcode_project: PhotoApp.xcodeproj xcode_scheme: PhotoApp script: - export SCAN_DEVICE="iPhone 7 (11.1)" - export SCAN_SCHEME=PhotoApp - export SCAN_DERIVED_DATA_PATH=$(pwd)/DerivedData - fastlane scan - if [ ! -e MagicPodDesktop*.*.*.zip ]; then curl -L -O "MagicPodDesktop.zipのダウンロードURL"; unzip -q MagicPodDesktop*.*.*.zip; fi - echo -n ${magic_pod_token} > ~/.magic_pod_token - Magic\ Pod\ Desktop.app/Contents/MacOS/Magic\ Pod\ Desktop run --magic_pod_config=$(pwd)/magic_pod_config.json
また、Travis CI向けに書き直した magic_pod_config.json は次のようになります。
{ "owner": "ATeam", "project": "MyIOSApp", "capabilities": { "platformName": "iOS", "platformVersion": "11.1", "deviceName": "iPhone 7", "automationName": "XCUITest", "app": "/Users/travis/build/hiroshitoda/PhotoApp/DerivedData/Build/Products/Debug-iphonesimulator/PhotoApp.app", "noReset": true }, "xmlTestOutput": true, "externalAppium": false, "debug": false, "serverUrl": "https://magic-pod.com", "workDir": "/Users/travis/build/hiroshitoda/PhotoApp/MagicPod", "testNumber": "1", "envVars": [], "appiumServerUrl": "", "sendMail": false }
CircleCIでの実行例
では次に、Travis CI向けの設定を参考に CircleCI 向けの設定を `circle.yml` に書いてみましょう。CircleCIでもfastlaneが使えますので、ほぼTravis CI向けと同じ設定になります。
version: 2 jobs: build: macos: xcode: "9.0" steps: - checkout - run: name: Install CocoaPods command: pod install # CircleCI向けのおまじないです。 # DerivedData内のフォルダーを事前に作成しないと、ビルドで失敗することがあります。 - run: name: make DerivedData dir command: mkdir -p $(pwd)/DerivedData/ModuleCache/Session.modulevalidation # fastlaneのバージョンが古すぎて動かない場合がありますので、 # テストの実行前に最新版に更新しましょう。 - run: name: Build and run tests command: | sudo gem install fastlane export LC_ALL=en_US.UTF-8 export LANG=en_US.UTF-8 fastlane scan environment: SCAN_DEVICE: iPhone 7 (11.0) SCAN_SCHEME: PhotoApp SCAN_DERIVED_DATA_PATH: $(pwd)/DerivedData - run: name: "Magic Pod Desktop download" command: | if [ ! -e MagicPodDesktop*.*.*.zip ]; then curl -L -O "MagicPodDesktop.zipのダウンロードURL" unzip -q MagicPodDesktop*.*.*.zip fi - run: name: "Magic Pod Desktop CLI" command: | echo -n ${magic_pod_token} > ~/.magic_pod_token "Magic Pod Desktop.app/Contents/MacOS/Magic Pod Desktop" run --magic_pod_config=$(pwd)/magic_pod_config.json
`magic_pod_config.json` は、CircleCIのディレクトリ構成を踏まえると次のように書き換えられます。
{ "owner": "ATeam", "project": "MyIOSApp", "capabilities": { "platformName": "iOS", "platformVersion": "11.0", "deviceName": "iPhone 7", "automationName": "XCUITest", "app": "/Users/distiller/project/DerivedData/Build/Products/Debug-iphonesimulator/PhotoApp.app", "noReset": true }, "xmlTestOutput": true, "externalAppium": false, "debug": false, "serverUrl": "https://magic-pod.com", "workDir": "/Users/distiller/project/MagicPod", "testNumber": "1", "envVars": [], "appiumServerUrl": "", "sendMail": false }
また、セキュリティトークン `.magic_pod_token` を保存するための環境変数は、CircleCIではプロジェクト設定の「Environment Variables」で設定できます。
以上の設定は、他のCIサービス向けに設定するときも同様なものです。この記事をご参考のうえ、Magic Podをぜひご利用中のCIサービスに組み込んでみてください。
Magic Podをはじめるには
Magic Podは、こちらのページから無料で始めることができます。この記事を読んで興味を持たれた方は、ぜひ一度試してみてください。
忙しくて時間が無いな〜とかビルドとかCIの設定がめんどくさいな〜とお悩みの方には、テストスクリプト作成サービスもご用意しています。
- 自動化のエキスパートが、あなたに代わってMagic Podのスクリプトを作成します。
- ビルド・CI環境の構築など、周辺環境の整備まで丸ごとお任せいただくこともできます。