iOS SDK 4 から追加された UIAutomation について調べてみました。
UIAutomation を使えば、JavaScript で UI の自動テストが可能になります。Instruments 上でターゲットのアプリと JavaScript のファイルをつなぐと実行できます。
詳しい導入方法はドキュメントを見てもらうとして、何ができるかをまとめてみました。
何ができるのか
- ログを出す
- 通常のログ出力
- 成功と失敗用のログ出力があって、それでテスト結果を判定する
- スクリーンショットをとる
- 画面全体または一部のスクリーンショットを撮影できる
- エラーの検知
- クラッシュなどがおきると JavaScript の例外がくる
- タップなどのユーザーのアクション
- ボタンなどの UI エレメントやデバイスに対して実行できる
- ドラッグ、フリック、ピンチイン、ピンチアウトなども可能
- UI の状態を取得
- 状態があっているかをテストする
- テキストの値や、有効状態を取得できる
- 回転ロックやボリュームコントロールのイベント
- 端末の回転
- UIDeviceOrientation と同じ6種類の get と set ができる
- マルチタスキング
- アプリをバックグラウンドにもっていける
- 設定
- ユーザデフォルトの値を設定できそう(未確認)
細かいできることはまだまだありますが、ざっとこんな感じです。UI 要素をたどるのが面倒なだけで、ユーザーのアクションはほぼ実現できそうです。
次に、実際のコードの書き方を紹介します。
まず最初に書く
// script の開始時に記述
UIALogger.logStart("テストの開始");
// 長くて面倒なので、初めに書いておく
var target = UIATarget.localTarget(); // デバイス (UIATarget)
var app = target.frontMostApp(); // アプリ (UIAApplication)
var window = app.window(); // Window (UIAWindow)
ログを用いてテスト関数を書く
//テストに失敗 (Instruments で赤色に)
UIALogger.logFail("Failed");
//テストに成功(Instrumentsで緑色に)
UIALogger.logPass("Success");
次のようなテスト関数を書いていけば、どのテストに失敗したか一目でわかるはず。
function testAdd() {
UIALogger.logMessage("testAddスタート");
try {
...
if (...) {
UIALogger.logPass("OK");
} else {
UIALogger.logFail("testAdd 失敗");
}
UIALogger.logPass("testAdd 成功");
} catch (e) {
// 例外
UIALogger.logFail("testAdd 失敗");
}
}
UIAElement をたどる
UIAutomation で UI 要素は UIAElement クラスとして定義されており、だいたいの UIView のサブクラスは 対応する UIAElement のサブクラスがあります。ただ、UIAWebView の Webページ自体も UIAElement で表現されていたりと少し UIKit とは違う構造になっているようです。UIAWindowが一番親なので、そこから子要素をたどっていって目的の UI 要素にアクセスします。
// これらは Window に属する
var statusBar = window.statusBar();
var tabBar = window.tabBar();
var naviBar = window.navigationBar();
var toolbar = window.toolbar();
// 1つ下の階層のUIAElementたちがUIAElementArrayで返る
var w_elems = window.elements();
var elem = w_elems[0];
var elems = element.elements();
// あるUIAElementクラスだけのUIAElementArray
var buttons = elem.buttons();
var images = elem.images();
// タップ
buttons[0].tap();
// ドラッグ
buttons[0].dragInsideWithOptions({startOffset:{x:0.0, y:0.5},
endOffset:{x:1.0, y:0.5},
duration:2.0});
スクリーンショットをとる
エラーが起きた時などに撮影しておけば、原因究明に役立ちます。
var rect = {
origin: {x:100, y:200},
size: {width:100, height:100}
};
target.captureRectWithName("imageName", rect);
// 画面全体
target.captureScreenWithName("imageName");
端末の回転
iOS SDK の 6つの UIDeviceOrientation に設定できます。細かい傾きの指定などはできないようです。
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_LANDSCAPELEFT);
UIALogger.logMessage("向きをLandscaleLeftに");
/* LandscapeLeftの状態でテスト */
...
*/
// 他のテストに影響を与えないように PORTRAIT に戻す
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_PORTRAIT);
UIALogger.logMessage("向きをPortraitに");
コントロール類
target.lock(); target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_PORTRAIT); // 確かに回転しない target.unlock(); target.clickVolumeUp(); target.holdVolumeUp(); target.clickVolumeDown(); target.holdVolumeDown();
マルチタスキング
UIALogger.logMessage("Deactivating app");
target.deactivateAppForDuration(10); // 10秒間バックグラウンドにいく
UIALogger.logMessage("Resuming test");
基本的にユーザーのタップを実現するだけなので、JavaScript のコードは単純です。JavaScript が初めてでもすぐに書けるようになると思うので、一度試してみてください。私も今後の開発で活用するつもりです。









