7

Apple の UIAutomation を使用して、サーバー側コンポーネントを持つ iOS アプリケーションの単体テストを作成しようとしています。テスト サーバーをさまざまな状態でセットアップする (およびサーバーを介して通信する 2 つのクライアントをシミュレートする) ために、javascript ベースのテスト内から HTTP get 要求を発行したいと考えています。

UIAutomation JavaScript テスト内から HTTP GET リクエストを直接発行する方法、または UIAutomation JavaScript テスト内からシェル スクリプトを呼び出す方法の例を誰かが提供できますか?

FWIW、すべてのブラウザーで利用できるコア オブジェクトのほとんどは、UIAutomation ランタイム内にありません。たとえば、XMLHTTPRequest を使用しようとすると、変数が見つからないという例外レポートが表示されます。

ありがとう!

4

5 に答える 5

5

皆さん、

HTTP リクエストを iOS クライアントに送信して処理し、結果を UIAlertView に返すことで、この問題を回避することができました。すべての iOS コードの変更は、#if DEBUG 条件付きコンパイル ディレクティブでラップされることに注意してください。

まず、デバイスが揺れた場合に通知を送信するようにクライアントをセットアップします。詳細については、この投稿をお読みください

次に、iOS メイン アプリ デリゲートに次のコードを追加します。

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(deviceShakenShowDebug:)
                                             name:@"DeviceShaken" 
                                           object:nil];

次に、次のようなメソッドを追加します。

- (void) deviceShakenShowDebug:(id)sender
{
    if (!self.textFieldEnterDebugArgs)
    {
        self.textFieldEnterDebugArgs = [[[UITextField alloc] initWithFrame:CGRectMake(0, 0, 260.0, 25.0)] autorelease];
        self.textFieldEnterDebugArgs.accessibilityLabel = @"AlertDebugArgsField";
        self.textFieldEnterDebugArgs.isAccessibilityElement = YES;
        [self.textFieldEnterDebugArgs setBackgroundColor:[UIColor whiteColor]];
        [self.tabBarController.selectedViewController.view addSubview:self.textFieldEnterDebugArgs];
        [self.tabBarController.selectedViewController.view bringSubviewToFront:self.textFieldEnterDebugArgs];
    }
    else
    {
        if ([self.textFieldEnterDebugArgs.text length] > 0)
        {
            if ([self.textFieldEnterDebugArgs.text hasPrefix:@"http://"])
            {
                [self doDebugHttpRequest:self.textFieldEnterDebugArgs.text];    
            }
        }
    }
}

- (void)requestDidFinishLoad:(TTURLRequest*)request
{
        NSString *response = [[[NSString alloc] initWithData:((TTURLDataResponse*)request.response).data 
                                                    encoding:NSUTF8StringEncoding] autorelease];

        UIAlertView *resultAlert = 
            [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Request Loaded",@"")
                                       message:response
                                      delegate:nil
                             cancelButtonTitle:NSLocalizedString(@"OK",@"")
                             otherButtonTitles:nil] autorelease];
        resultAlert.accessibilityLabel = @"AlertDebugResult";
        [resultAlert show];
}

このコードは、ナビゲーション バーまたはその他の UI 要素の真上に叩きつけられた後、一番上のビュー コントローラーに UITextField を追加します。UIAutomation またはユーザーは、この UITextField に手動で URL を入力できます。もう一度デバイスを振ると、テキストが「http」で始まる場合、コードで HTTP リクエストが発行されます (リーダーが doDebugHttpRequest を実装するための演習)。

次に、UIAutomation JavaScript ファイルで、次の 2 つの関数を定義しました。

function httpGet(url, delayInSec) {
  if (!delayInSec) delay = 1;
  var alertDebugResultSeen = false;
  var httpResponseValue = null;

  UIATarget.onAlert = function onAlert(alert) {    
    httpResponseValue = alert.staticTexts().toArray()[1].name();
    alert.buttons()[0].tap();
    alertDebugResultSeen = true;
  }

  var target = UIATarget.localTarget();
  var application = target.frontMostApp();
  target.shake(); // bring up the input field
  application.mainWindow().textFields()["AlertDebugArgsField"].setValue(url);
  target.shake(); // send back to be processed
  target.delay(delayInSec);
  assertTrue(alertDebugResultSeen);
  return httpResponseValue;
}

function httpGetJSON(url, delayInSec) {
  var response = httpGet(url, delayInSec);
  return eval('(' + response + ')');
}

今、私のjavascriptファイルで、私は呼び出すことができます

httpGet('http://localhost:3000/do_something')

HTTP リクエストを実行します。サーバーから JSON データを返したい場合は、

var jsonResponse = httpGetJSON('http://localhost:3000/do_something')

長時間の通話になることがわかっている場合は、電話します

var jsonResponse = httpGetJSON('http://localhost:3000/do_something', 10 /* timeout */)

私はこのアプローチを数週間うまく使用しています。

于 2011-07-28T06:20:56.317 に答える
4

PerformTaskWithPathArgumentsTimeoutを試してください

UIATarget.host().performTaskWithPathArgumentsTimeout("/usr/bin/curl", "http://google.com", 30);
于 2011-12-30T15:31:05.293 に答える
3

ちょっとだけ訂正。UIATarget.host().performTaskWithPathArgumentsTimeout の使用を提案する回答は、iOS 5.0 以降で URL に対して要求を行う簡単な方法ですが、例の構文は正しくありません。この呼び出しを行う正しい方法は次のとおりです。

UIATarget.host().performTaskWithPathArgumentsTimeout("/usr/bin/curl", ["http://google.com"], 30);

「args」パラメーターを囲む「[」は重要であり、括弧を忘れると、次のような例外が発生してテストが終了します。

エラー: -[__NSCFString count]: 認識できないセレクターがインスタンスに送信されました

google.com にヒットし、すべての出力をログに記録する完全に機能する例を次に示します。

var result = UIATarget.host().performTaskWithPathArgumentsTimeout("/usr/bin/curl", ["http://www.google.com"], 30);

UIALogger.logDebug("exitCode: " + result.exitCode);

UIALogger.logDebug("stdout: " + result.stdout);

UIALogger.logDebug("stderr: " + result.stderr);
于 2012-08-28T00:07:54.527 に答える
2

「shake()」の創造的な使用のための+1。ただし、一部のプロジェクト、特にシェイク機能を実際に使用するプロジェクトでは、これはオプションではありません。

既成概念にとらわれずに考えてください。他のもの (Python、Ruby、node.js、bash+wget など) でフェッチを行います。次に、事前に用意された応答を使用して、その動的に生成された json ペイロードを「サンプル データ」としてテストに含めることにより、オンザフライで ui-test.js を自動生成できます。次に、テストを実行するだけです。

私の意見では、テストはテストです。使用しているテスト データが動的である場合は、テスト自体から分離する必要があります。この方法で JSON を取得/生成し、テストから参照することで、各テストの直前に、またはサーバーが更新されたことを知っているときのように設定された間隔で、好きな頻度でその JSON を更新できます。テストの実行中にそれを生成したいかどうかはわかりませんが、問題が発生するようです。それを次のレベルに引き上げると、他の値に基づいてどの値が必要かを計算する関数を使用して、その数学がテスト内にあるのではなく、データの「動的プロパティ」として公開することができます。

于 2011-08-01T20:11:32.593 に答える
2

Apple は最近、テストを実行している Instruments のインスタンスを実行しているホストでタスクを実行するUIAutomationための新しいUIAHost要素を含めるように更新しました。

于 2011-12-08T22:56:31.663 に答える