iOSアプリケーションの自動テスト

画像

モバイルアプリケーションのインターフェイスが再び折りたたまれたかどうかを監視する必要がある場合があります。 この問題を解決するには、自動テストが使用されます。 Webページの場合、Selenium Webドライバーを使用するのが一般的な方法と考えられているため、モバイルアプリケーションの場合は、同様のものを探していました。 そして、幸いにもそれらの多くがあり、それらはSelenium WebDriver JSON Wire Protocolを使用しています。



この記事ではAppiumに焦点を当てます。 この種のすべての製品で同じドライバーが使用されているかどうかは特に確認しませんでした。 しかし、私がAppiumを選んだ理由は、すべての一般的な言語のサポートがメインページで明確に示されているためです。 ここに彼らが誇るものがあります:

  1. アプリケーションを再コンパイルまたは変更する必要はありません。これは、すべてのプラットフォームで標準の自動化APIを使用することで実現されます。
  2. Java、Objective-C、Node.jsを使用したJavaScript(コールバックとyieldベースのメソッドの両方)、PHP、Python、Ruby、C#、ClojureなどのWebDriver互換言語を使用して、お気に入りの開発ツールでテストを記述できます。またはSelenium WebDriver APIと特定のクライアントライブラリを備えたPerl。
  3. 任意のテストフレームワークを使用できます。


必要になります



実際、彼はまだAndroidとFirefoxOSを知っています。 この記事ではiOSについてのみ説明していますが、プラットフォームを変更してもコードはそれほど変わりません。 Appiumサーバーをインストールすることから始めましょう。 ここからアプリケーションをダウンロードするか、npm からインストールできます。 必要に応じて「sudo」を追加します。



$ npm install -g appium $ appium &
      
      





iOSシミュレーターの使用を許可する必要があります。 NPMでAppiumを実行している場合は、「sudo authorize_ios」と入力してこれを行います(authorize_iosはAppium npmパッケージのバイナリファイルです)。 ソースからAppiumを起動する場合、コマンド「sudo grunt authorize」を使用します。 または、Appium.appプログラムのグラフィカルインターフェイスを使用して実行します。



テストの作成を始めましょう。 明らかな理由により、作業中のドラフトは提供しません。 簡単なケースについて説明します。

  1. ボタンが出ました
  2. その場所のボタン
  3. ワーキングボタン
  4. ボタンが壊れています


AppiumはTapsterなどのロボットで使用できます。 ロボットの詳細例は こちら 。 しかし、この記事はそれらについてではありません..



ソースコードとサンプルアプリケーションをテストします。 2つの同一のアプリケーションがあり、1つはObjectiveCで作成され、2つ目はTitaniumで作成されています。 これは、結果としてネイティブiOS要素が表示される場合、UIを作成する方法が重要でないことを明確にするためです。



テスト例を分析します。



 var wd = require("wd") , assert = require("assert") ,Q = require("q") , appURL = __dirname+'/../program/Apps/Titanium/AppiumStudy.app'; // Instantiate a new browser session var browser = wd.promiseRemote("localhost", 4723); // See whats going on browser.on("status", function(info) { console.log('\x1b[36m%s\x1b[0m', info); }); browser.on("command", function(meth, path, data) { console.log(' > \x1b[33m%s\x1b[0m: %s', meth, path, data || ''); });
      
      





モジュールの接続。 wdは、Selenium Webドライバーの標準バインダーです。 appURLでは、アプリケーションまたはそのアーカイブまたはそのhttpアドレスへのパスを指定できます。 デバッグ情報を表示するためだけのイベントハンドラー。必要ない場合は、安全に削除できます。 これで、Webドライバーが初期化され、テスト機能が実行されます。



 browser .init({ device: "" , name: "Appium: with WD" , platform: "Mac" , app: appURL , version: "6.0" , browserName: "" , newCommandTimeout: 60 }) .then(function () { return browser.elementsByTagName('button'); }) .then(check_buttons) .fail(function (err) { console.log('fail', err) }) .fin(function () { browser.quit(); }) .done();
      
      





そして、テスト自体:



 var check_buttons = function(els){ assert.equal(els.length, 4, 'Not enough buttons'); var check_first_buttons = function(els){ var deferred = Q.defer(); var check_alert = function(ValidButton){ var deferred = Q.defer(); browser.clickElement(ValidButton) .then(function(){ return browser.elementsByTagName('alert'); }) .then(function(alert){ assert.equal(alert.length, 1, "Alert not shoved"); return browser.acceptAlert(); }) .fail(function(err){ deferred.reject(new Error(err.message)); }) .fin(function(){ deferred.resolve(); }); return deferred.promise; } var check_invalid_position = function(InvalidButton){ var deferred = Q.defer(); InvalidButton.getLocation() .then(function(location){ assert.equal(location.x, 43, "InvalidButton location is not wrong"); }) .fail(function(err){ deferred.reject(new Error(err.message)); }) .fin(function(els){ deferred.resolve(); }); return deferred.promise; } var check_valid_position = function(ValidButton){ var deferred = Q.defer(); ValidButton.getLocation() .then(function(location){ assert.equal(location.x, 20, 'ValidButton location is wrong'); }) .fail(function(err){ deferred.reject(new Error(err.message)); }) .fin(function(els){ deferred.resolve(); }); return deferred.promise; } check_alert(els[0]) .then(function(){return check_invalid_position(els[1]);}) .then(function(){return check_valid_position(els[0]);}) .fin(function(){ deferred.resolve(els); }); return deferred.promise; } var check_work_button = function(work_button){ var deferred = Q.defer(); work_button.click() .then(function(){ return browser.waitForElementByTagName('text'); }) .then(function(){ return work_button.displayed(); }) .then(function(displayed){ assert.equal(displayed, false, "Work button still visible"); }) .then(function () { return browser.elementsByTagName('text'); }) .then(function (label) { assert.equal(label.length, 1, "Label not found"); return label[0].text(); }) .then(function (text) { assert.equal(text, 'I am live!', "Label text not matched"); }) .fail(function(err){ deferred.reject(new Error(err.message)); }) .fin(function(){ // deferred.resolve(els); }); return deferred.promise; } var check_broken_button = function(broken_button){ var deferred = Q.defer(); broken_button.click() .then(function(){ return broken_button.displayed(); }) .then(function(displayed){ assert.equal(displayed, false, "Broken button still visible"); }) .fail(function(err){ deferred.reject(new Error(err.message)); }) .fin(function(){ deferred.resolve(els); }); return deferred.promise; } var deferred = Q.defer(); check_first_buttons(els) .then(function(){return check_work_button(els[2]);}) .fail(function(err){ deferred.reject(new Error(err.message)); }) .fin(function(){ deferred.resolve(); }); return deferred.promise; }
      
      





「check_invalid_position」では、要素が実際に移動したかどうかを確認するチェックが行われますが、これは完全に論理的ではありません。 それがその場所にあるかどうかを確認する方が正しいでしょうが、アサートは最初のエラーでテストを中断します。 大丈夫です、主なことは、そうであるべきだと知っていることです。



要素セレクターの設定が困難な場合は、Appium Inspectorを使用できます。 これを行うには、npmバージョンを使用している場合はアプリケーションをダウンロードし、「停止」ボタンの左側にある青色の情報アイコンが付いたボタンをクリックします。 詳細はこちら







テストが進行すると、現在のテスタータスクがコンソールに表示されます。



 $ node test.js Driving the web on session: 4892e40c-3cdf-4b66-9a01-4bfbad23da67 > POST: /session/:sessionID/elements { using: 'tag name', value: 'button' } > POST: /session/:sessionID/element/0/click > POST: /session/:sessionID/elements { using: 'tag name', value: 'alert' } > POST: /session/:sessionID/accept_alert > GET: /session/:sessionID/element/1/location > GET: /session/:sessionID/element/0/location > POST: /session/:sessionID/element/2/click > POST: /session/:sessionID/elements { using: 'tag name', value: 'text' } > GET: /session/:sessionID/element/2/displayed > POST: /session/:sessionID/elements { using: 'tag name', value: 'text' } > GET: /session/:sessionID/element/6/text > DELETE: /session/:sessionID Ending your web drivage..
      
      





またはエラーメッセージ。 非アクティブなボタンを使用して新しいモーダルウィンドウを開くためのチェックを追加すると、次のようになります。



  check_first_buttons(els) .then(function(){return check_broken_button(els[3]);}) .then(function(){return check_work_button(els[2]);}) .fail(function(err){ deferred.reject(new Error(err.message)); }) .fin(function(){ deferred.resolve(); });
      
      





 $ node test.js Driving the web on session: 4a5f1d13-b395-49a0-a28f-2d2cd67ac72d > POST: /session/:sessionID/elements { using: 'tag name', value: 'button' } > POST: /session/:sessionID/element/0/click > POST: /session/:sessionID/elements { using: 'tag name', value: 'alert' } > POST: /session/:sessionID/accept_alert > GET: /session/:sessionID/element/1/location > GET: /session/:sessionID/element/0/location > POST: /session/:sessionID/element/3/click > GET: /session/:sessionID/element/3/displayed fail [Error: Broken button still visible] > DELETE: /session/:sessionID Ending your web drivage..
      
      





また、appium自体でログを見ることができます







Appiumのドキュメントにはまだ少し注意が必要です。 ただし、 wdでコマンドの説明とリストを確認できます。 質問がある場合は、コメントを書くか、PMに書いてください。 したがって、モバイルアプリケーションインターフェイスをテストするルーチン作業の一部をコンピューターの肩に移すことができます。



All Articles