はじめに
このページは、Appium を使用してiOS/Androidのテストを書く際の流れについてまとめた記事です。
とくに、Appiumの特徴でもある Appium.app の Inspector機能 を使用した、アプリの構造解析方法 にフォーカスを当てて説明していきたいと思います。
テストを書く流れ
Appiumを使用したiOS、Androidアプリのテストは、大まかに下記の流れで作成します。
-
アプリのバイナリ (iOSの場合は
app
またはipa
、Androidの場合はapk
ファイル)を用意する
または、実機を使用する場合はあらかじめアプリを端末にインストールしておく - Appium.app の Inspector 機能を使用して、実際にアプリを操作しながら必要な画面要素を調査する
- 調査した情報をもとに、お気に入りの言語(Java, Ruby, Python...)でテストスクリプトを書く
使用可能なアプリのバイナリについて
Appiumでは、iOSの場合、使用するアプリは Developmentのプロビジョニングプロファイル でビルドされた、いわゆる 開発用 のアプリである必要があります。 Relese用 のアプリはもちろんのこと、 AdHoc用 に配布されたもの、 Enterprise用(企業向け) のものは使用できないので注意が必要です。
※これはAppiumの制限というよりも、Appiumが内部で使用している UIAutomationの仕様 です。
その点、Androidの場合はそういった制限がありませんので、例えば Google Playからインストールしたアプリ をそのままAppiumでテストすることも可能です。
Appium.app(GUI)を使う
Appium.app は、それ単体でAppiumサーバの起動/終了をしたり、iOS/Androidアプリの構造解析ができるMac用のGUIアプリケーションです。
iOS/Androidのテストを書く際には、アプリ画面の要素(ボタンやテキストフィールド)の情報(IDや階層情報)が必要になるため、都度、実際のアプリを操作しながら、このAppium.app
を使用して要素を調べていきます。
Appium.appの入手方法
Appiumの公式サイトまたはGitHubから、dmgファイル(appium-xxx.dmg)をダウンロードします。
※ 公式サイトよりGitHubの方が更新ペースが早いようです。
ダウンロードしたファイルはダブルクリックしてマウント後、Applications
フォルダにコピーします。
初期設定
Appium.app をダブルクリックして起動したら、 iOS または Android アイコンのボタンをクリックして各種設定を行います。
設定する箇所は、 シミュレータを使用する場合 と Macに接続された実機を使用する場合 とで一部異なります。
iOSの場合
設定項目 | 説明 | 設定例 | (シミュレータ) | (実機) |
---|---|---|---|---|
App Path | appまたはipaファイルの絶対パスを指定 | /Users/kzm/work/app/MyApp.app | ○ | |
BundleID | アプリの識別子を指定 | com.example.myapp | ○ | |
Force Device | 機種名を指定 | iPhone 5s | ○ | ○ |
Platform Version | OSバージョンを指定 | 7.1 | ○ | ○ |
UDID | 端末のUDIDを指定 | 887gpwqs9sd2jhd30r78934020gdj20dge89s9kz | ○ | |
Full Reset | 端末のUDIDを指定 | 887gpwqs9sd2jhd30r78934020gdj20dge89s9kz | ○ |
Androidの場合
設定項目 | 説明 | 設定例 | (シミュレータ) | (実機) |
---|---|---|---|---|
App Path | apkファイルの絶対パスを指定 | /Users/kzm/work/app/MyApp.apk | ○ | |
Package | ※ 後述 | com.example.myapp | ○ | |
Launch Activity | ※ 後述 | .main.ToMainActivity | ○ | ○ |
Platform Name | プラットフォームを指定 | Android | ○ | ○ |
Automation Name | 使用する自動化ツールを指定 | Appium | ○ | ○ |
Platform Version | OSバージョンを指定 | 4.4 KitKat (API Level 19) | ○ | ○ |
Device Name | 機種名を指定 | Android Emulator | ○ | ○ |
※ PackageとActivityの調べ方
【方法①】apkファイルから調べる
- AXMLPrinter2.jarをダウンロードして任意のフォルダに格納しておく
- アプリのバイナリの拡張子を apk から zip に変更して展開
- 展開したフォルダ内の AndroidManifest.xml ファイルを AXMLPrinter2.jar と同じディレクトリにコピー
- ターミナルで以下のコマンドを実行
java -jar AXMLPrinter2.jar AndroidManifest.xml
- 出力された結果の以下の箇所を参照する
manifestセクション
package="com.example.myapp"
activityセクション
android:name=".main.ToMainActivity"
【方法②】端末にインストールされたアプリから調べる
事前準備:MacにAndroid端末を接続し、対象のアプリを起動しておく
- インストール済みのパッケージ一覧を取得するコマンド
adb shell pm list packages
adb shell pm list packages nttdocomo
- 現在起動しているActivityを調べるコマンド
adb shell dumpsys activity | grep "android.intent.category.LAUNCHER.*<パッケージ名>"
例えばFacebookアプリの場合、コマンドを実行すると下記の情報が取得できます。
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 pkg=com.facebook.katana cmp=com.facebook.katana/com.facebook.nodex.startup.splashscreen.NodexSplashActivity }
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 pkg=com.facebook.katana cmp=com.facebook.katana/.LoginActivity bnds=[0,498][270,837] }
この例では以下の箇所がActivityになります。
cmp=com.facebook.katana/.LoginActivity
実際にAppiumのLaunch Activity
に設定する際は、上記値からパッケージ名を除いた .LoginActivity の部分を指定します。
なお、Activityの取得は アプリをタスクマネージャから完全に終了した状態から起動した直後 に行います。
アプリによっては複数のActivityが表示される場合がありますが、その場合は名前で判断しましょう。
Inspectorでアプリの構造を解析
起動方法
設定が完了したら、 Launch ボタンをクリックしてAppiumサーバを起動します。
既にターミナルからAppiumサーバを起動済みの場合は、一旦終了してからLaunchボタンで再度起動しましょう。
killall -9 node
下記のようなログが出力されたら準備完了です。
info: Welcome to Appium v1.3.1 (REV 1160ce02bb89c354cb99317985123acf39f0e7d3)
info: Appium REST http interface listener started on 0.0.0.0:4723
info: [debug] Non-default server args: {"app":"/Users/kzm/work/app/MyApp.app","deviceName":"iPhone 5s","defaultCommandTimeout":7200}
info: Console LogLevel: debug
info: --> GET /wd/hub/status {}
info: [debug] Responding to client with success: {"status":0,"value":{"build":{"version":"1.3.1","revision":"1160ce02bb89c354cb99317985123acf39f0e7d3"}}}
info: <-- GET /wd/hub/status 200 5.250 ms - 104 {"status":0,"value":{"build":{"version":"1.3.1","revision":"1160ce02bb89c354cb99317985123acf39f0e7d3"}}}
虫眼鏡 ボタンをクリックしてInspectorを起動します。
Inspectorを起動すると、同時にシミュレータまたは端末上で自動的にアプリが立ち上がります。
使い方
Inspector内に表示されているアプリのスクリーンショットをマウスでクリックすると、選択した要素の情報が Details
エリア内に表示されます。
下記はiOS、Androidアプリでテキストフィールドの情報を取得した際の例です。
name: login_username
type: UIATextField
value: メールまたは携帯番号
label:
enabled: true
visible: false
valid: true
location: {5, 124}
size: {315, 44}
xpath: //UIAApplication[1]/UIAWindow[1]/UIATableView[1]/UIATableCell[1]/UIATextField[1]
content-desc:
type: android.widget.EditText
text: メールまたは携帯番号
index: 1
enabled: true
visible: true
location: {96, 667}
size: {888, 120}
checkable: false
checked: false
focusable: true
long-clickable: true
package: com.example.myapp
password: false
resource-id: com.example.myapp:id/login_username
scrollable: false
selected: false
xpath: //android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.EditText[1]
上記の name (iOSの場合) や resource-id (Androidの場合) が、HTMLでいう id や class に該当します。
ただし通常、テストの自動化を考慮していないアプリではこれらの値は設定されていないケースが多いため、その場合は type や xpath を使用して要素を特定することになります。
ちなみにiOSではアプリを開発する際、要素に accessibilityIdentifier または accessibilityLabel を設定しておくことで、Appiumから name として値が取得できるようになります。
また、accessibilityIdentifierを明示的に設定していなくても、例えば UITableCell は text プロパティに設定された文字列がそのまま name に設定されます。
このように、たとえAppiumでUIテストを行うことを予め想定して開発していなくても(意識的にIDを振っていなくても)、iOS/AndroidアプリのUIテストを自動化することは十分可能です。