从iOS UIAutomation发出JavaScript中的同步HTTP GET请求或调用shell脚本

我正在尝试使用Apple的UIAutomation为具有服务器端组件的iOS应用程序编写unit testing。 为了在各种状态下设置测试服务器(以及模拟通过我的服务器进行通信的两个客户端),我想在基于javascript的测试中发出HTTP get请求。

任何人都可以提供一个示例,说明如何直接从UIAutomation javascript测试中发出HTTP GET请求,或者如何从我的UIAutomation javascript测试中调用shell脚本?

FWIW,UIAutomation运行时中缺少所有浏览器提供的大多数核心对象。 例如,尝试使用XMLHTTPRequest,您将收到一个exception报告,它无法找到该变量。

谢谢!

伙计们,

我能够通过向iOS客户端发送HTTP请求来处理并在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]; } 

此代码将在摇动后向顶部视图控制器添加UITextField,在任何导航栏或其他UI元素上方拍打。 UIAutomation或您的用户可以手动在此UITextField中输入URL。 再次摇动设备时,如果文本以“http”开头,它将在代码中发出HTTP请求(练习让读者实现doDebugHttpRequest)。

然后,在我的UIAutomation JavaScript文件中,我定义了以下两个函数:

 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 */) 

我已经成功使用这种方法已有好几周了。

尝试performTaskWithPathArgumentsTimeout

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

只是一个小小的修正。 建议使用UIATarget.host()。performTaskWithPathArgumentsTimeout的答案是在iOS 5.0+中对URL发出请求的简单方法,但该示例的语法不正确。 以下是进行此调用的正确方法:

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

“args”参数周围的“[”很重要,如果忘记括号,测试将会死于类似下面的exception:

错误: – [__ 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); 

+1创造性地使用“shake()”。 但是,对于某些项目来说,这不是一个选项,特别是那些实际使用摇动function的项目。

创造性思考。 用其他东西(Python,Ruby,node.js,bash + wget等)进行提取。 然后,您可以使用预先设定的响应并通过将动态生成的json有效负载作为“样本数据”包含在测试中来动态生成ui-test.js。 然后你只需执行测试。

在我看来,测试是测试,单独留下。 您正在使用的测试数据,如果它是动态的,它应该与测试本身分开。 通过这种方式获取/生成JSON并从测试中引用它,您可以在每次测试之前立即更新该JSON,或者在您知道服务器已更新的设置时间间隔内更新。 我不确定你是否想在测试运行时生成它,这似乎会产生问题。 将它提升到一个新的水平,你可以得到想象并使用函数来计算应该基于其他值的值,并将它们作为数据的“动态属性”公开,而不是将数学放在测试中,而是在我认为讨论更多的是学术讨论,而不是实际的讨论。

Apple最近更新了UIAHost以包含一个新的UIAHost元素,用于在运行正在执行测试的Instruments实例的主机上执行任务 。