Issue a synchronous HTTP GET request or call a shell script in JavaScript from iOS UIAutomation

I am trying to use Apple UIAutomation to write unit tests for an iOS application that has a server component. To configure the test server in different states (as well as simulate two clients interacting through my server), I would like to receive HTTP requests to receive from my javascript based test.

Can someone provide an example of how to either issue HTTP GET requests directly from the javascript UIAutomation tests, or how to call a shell script from my javascript tests in UIAutomation?

FWIW, most of the core objects available for all browsers are missing from the UIAutomation runtime. Try using XMLHTTPRequest, for example, and you get an exception report that the variable cannot find.

Thanks!

+7
source share
5 answers

People,

I managed to get around this by sending HTTP requests to the iOS client to process and return the results to UIAlertView. Please note that all modifications to iOS code are wrapped in #if DEBUG conditional compilation directives.

First, configure the client to send notifications when the device is shaken. Read this post for more information .

Next, in your applet for the main iOS app, add this code:

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

Then add a method that looks something like this:

 - (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]; } 

This code will add a UITextField to the controller of the topmost view after shaking, hit right above any navigation bar or other user interface element. The UIAutomation, or user, can manually enter the URL into this UITextField. When you shake the device again, if the text starts with "http", it will issue an HTTP request in code (reading exercise for doDebugHttpRequest).

Then, in my UIAutomation JavaScript file, I defined the following two functions:

 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 + ')'); } 

Now, in my javascript file, I can call

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

and it will execute an HTTP request. If I want to return JSON data from the server, I call

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

If I know it will be a long call, I call

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

I have been using this approach successfully for several weeks now.

+5
source

Try performTaskWithPathArgumentsTimeout

 UIATarget.host().performTaskWithPathArgumentsTimeout("/usr/bin/curl", "http://google.com", 30); 
+5
source

Just a little correction. An answer that suggests using UIATarget.host (). ExecuteTaskWithPathArgumentsTimeout is an easy way to query a URL in iOS 5.0+, but the syntax for the example is incorrect. Here is the right way to make this call:

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

The "[" around the "args" parameter is important, and the test will die with an exception similar to the following if you forget the brackets:

Error: - [__ NSCFString count]: unrecognized selector sent to instance

Here is a complete working example that shows google.com and records all the output:

 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); 
+3
source

+1 for creative use of "shake ()". However, this is not an option for some projects, especially those that actually use the shake function.

Think outside the box. Make a choice with something else (Python, Ruby, node.js, bash + wget, etc.). Then you can use the pre-programmed response and automatically generate ui-test.js on the fly by including the dynamically generated json payload as “sample data” in the test. Then you just do the test.

In my opinion, a test is a test, leave it alone. The test data that you use, if it is dynamic, it should be separated from the test itself. By performing this method of obtaining / generating JSON and referring to it from the test, you can update this JSON, as you often like, either immediately before each test or at a specified interval, for example, when you know that the server is updated. I'm not sure if you want to generate it while running the test, it looks like this will create problems. Moving to the next level, you can get fantasies and use functions that calculate which values ​​should be based on other values, and expose them as the "dynamic properties" of the data, not this math inside the test, but in doing so, I believe that the discussion is more academic than practical.

+2
source

Apple recently updated UIAutomation to add a new UIAHost element to perform the task on the host on which the UIAHost Execution Tools instance is running.

+2
source

All Articles