最近研究iOS自动化测试,发现网上很少资料,不得不自己扒着官网学习。
首先,自动化测试的目的就是方便测试人员,工作周期上减少了时间。
第一部分:
打开Xcode6.0,选择你要自动化测试的工程,使用快捷键command + I打开测试工具,选择Automation。如图是选择Automation之后的效果。
之后我们选择上图红圈1的蓝色按钮,接着点击add。选择create,创建一个新的脚本。
如果想使用之前写好的脚本,点击add,选择import。写好的脚本想保存,在编辑界面鼠标右键,点击export。
之后选红圈3打开相应脚本,选择红圈4找到你要的应用,看见play按钮了吧,直接点击就会运行你的脚本来进行自动测试。
第二部分:
其次就是如何使用,语言选择javascript,苹果已经帮你封装好了一套UI Automation API,你直接调用就可以了。还是提供了不少方便的。
先运行一个简单的脚本,这里先不用理解脚本的具体含义。后面会讲。先看效果。
脚本代码:
UIALogger.logStart("Logging element tree ...");
UIATarget.localTarget().logElementTree();
UIALogger.logPass();
代码粘贴过去,点击play。运行结果如图:
选择Editor Log选项,看到一个绿色的Pass,证明这个测试已经通过了。同时,观察元素的层次关系。
(1)得到指定的元素。
要测试一个UI,必须通过UI Automation API得到它,UIAElement是API的基类,相当于NSObject。你可以指定任何一个元素唯一的一个的名字来标示它。官网有通过XIB设置的。这里用代码讲解,比如在一个View.m中UIButton实例button,我们设置
button.isAccessibilityElement = YES;
button.accessibilityLabel = @"Search"。
那么在automating.js中得到这个按钮的代码:var searchBt = UIAtarget.localTarget().frontMostApp().windows()["assistive"].buttons()["Search"];
这里是根据我的iDemo中得到的,不同的代码方括号[]中得内容可能不同。
模拟点击事件就更简单了,searchBt.tap();
再举一个文本框的例子:UIATarget.localTarget().frontMostApp().mainWindow().textFields()[0].setValue("我是文本框");
该句代码实现了找到指定的文本框,并且这只文本框值的功能。
另外还有很多控件,在UI Automation API都有对应的类和方法使用。这里不再详述。至于手势的使用看官方文档。很简单。
(2)判断该元素是否存在
为了增加脚本的健壮性。我们需要判断是否取到了相应的元素,在得到之后才能调用相应的tap(),setValue()等方法。
这里var searchBt = UIAtarget.localTarget().frontMostApp().windows()["assistive"].buttons()["Search"];得到
但是不能通过
if(searchBt){
}
else
{
}
简单判断。我也没有搞懂。用javascript的判断方法似乎也不行。现象是每次都为真。这里只能通过Apple的方法。isValid()去判断。
if(searchBt.isValid()){
UIALogger.logPass("Found");
}
else
{
UIALogger.logFail("Not Found. Test Fail");
}
以上部分完成了对一个按钮的自动测试,当有的时候,打印Found,在没有的时候打印Not Found.Test Fail。这个时候切换到Edit Log界面可以看到红色的Fail。Instrument tool告诉你自动测试那些模块过了,那些没过。
(3)让脚本更加方便
使用的人会觉得很不方便原因之一是不能调试,那么增加log就很重要。苹果建议:When writing your tests, you should log as much information as you can, if just to help you diagnose any failures that occur. At a bare minimum, you should log when each test begins and ends, identifying the test performed and recording pass/fail status.
UIALogger.logStart("验证搜索按钮");
//验证代码
UIALogger.logMessage("已经存在,下面验证点击");
//验证代码
UIALogger.logPass("验证完成");
(4)定时机制
在访问一个组件的时候,可能由于程序再启动过程,屏幕还没有绘制完成,或者元素正在绘制导致失败。这个时候,你的脚本应该等待执行。
比如你设置一个超时时间UIATarget.localTarget().pushTimeout(2);
然后写你的测试代码。
取消这个超时UIATarget.localTarget().popTimeout();
那么在这两句之间的代码就是当前超时时间下来运行。
(5)处理警告
在程序运行中往往产生alert,不管是系统的还是自己代码控制的,
系统的alert
UIATarget.onAlert = function onAlert(alert) {
var title = alert.name();
UIALogger.logWarning("Alert with title '" + title + "' encountered.");
// return false to use the default handler
return false;
}
返回false标示不予理会这个alert,就好像整个程序过程中没有外部警告出现。
程序的alert
UIATarget.onAlert = function onAlert(alert) {
var title = alert.name();
UIALogger.logWarning("Alert with title '" + title + "' encountered.");
if (title == "The Alert We Expected") {
alert.buttons()["Continue"].tap();
return true; //alert handled, so bypass the default handler
}
// return false to use the default handler
return false;
}
(5)模拟后台
UIATarget.localTarget().deactivateAppForDuration(10);
暂停脚本,模拟点击home键,10s后返回前台。
(6)模拟方向
var target = UIATarget.localTarget();
var app = target.frontMostApp();
// set landscape left
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_LANDSCAPELEFT);
UIALogger.logMessage("Current orientation is " + app.interfaceOrientation());
// portrait
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_PORTRAIT);
UIALogger.logMessage("Current orientation is " + app.interfaceOrientation());
(7)脚本截图
var target = UIATarget.localTarget();
target.captureScreenWithName( "screenshot1.png" );