问题描述
|
我正在尝试使用Apple的UIAutomation为具有服务器端组件的iOS应用程序编写单元测试。为了在各种状态下设置测试服务器(以及模拟通过我的服务器进行通信的两个客户端),我想在基于JavaScript的测试中发出HTTP get请求。
谁能提供一个示例,说明如何直接从UIAutomation javascript测试内发出HTTP GET请求,或者如何从UIAutomation javascript测试内调用Shell脚本?
FWIW,UIAutomation运行时中缺少所有浏览器提供的大多数核心对象。例如,尝试使用XMLHTTPRequest,您将收到一个异常报告,指出它找不到该变量。
谢谢!
解决方法
民间,
通过将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,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 \”参数周围的\“ [\”很重要,并且如果忘记括号,该测试将以类似于以下的异常终止:
错误:-[__ NSCFString计数]:无法识别的选择器已发送到实例
这是一个完整的示例,可访问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()\”。但是,对于某些项目,尤其是那些实际使用摇动功能的项目,这不是一个选择。
创造性思考。使用其他内容(Python,Ruby,node.js,bash + wget等)进行提取。然后,您可以使用预先设置的响应,并通过将动态生成的json有效内容作为“样本数据”包含到测试中来动态地自动生成ui-test.js。然后,您只需执行测试。
在我看来,测试就是测试,别说了。您正在使用的测试数据,如果是动态的,则应与测试本身分开。通过以这种方式获取/生成JSON并从测试中引用它的方式,您可以随时随地更新JSON,可以在每次测试之前立即更新,也可以在固定的时间间隔(例如您知道服务器已更新)进行更新。我不确定您是否要在测试运行时生成它,这似乎会产生问题。将其带入一个新的水平,您可能会发现并使用函数来计算应该基于其他值的值,并将它们显示为数据的“动态属性”,而不是将数学作为测试的一部分,但是在这一点上,我认为讨论更多是学术性的而不是实践性的。
, Apple最近对ѭ9进行了更新,以包括一个新的for10元素,用于在运行正在执行测试的Instruments实例的主机上执行任务。