相对于Android来讲,iOS比较封闭。这一点,在设计和评估自动化测试方案的时候感受尤为强烈。iOS平台上没有特别好用的自动化测试工具。苹果针对iOS提供了UI Automation的Instruments工具,以及相配合使用的Javascript库,可是使用起来有很大的局限性。主要问题是必须使用Javascript来编写测试脚本,不支持其余语言,很难实现复杂的功能。并且,在一台mac机上同时只能运行一个Instruments实例,没法对多个设备同时进行测试。在多数游戏应用中,UI都不是使用标准控件的,因此不可避免的要使用图像识别技术。而iOS UI Automation API里面除了截屏的功能并无提供多少帮助。html
所幸的是咱们找到了UIAHost.performTaskWithPathArgumentsTimeout()方法。这个方法是用来调用外部程序的。巧妙地利用这个方法能够实现比较复杂的功能。可是我仍然但愿测试逻辑能用Python来写,由于Python用起来至关顺手并且有成熟的测试框架。python
要让UI Automation的Javascript脚本遵从Python脚本的指挥,能够把Javascript脚本写成一个服务器,接受来自Python脚本的指令,并调用相应的API完成任务。通讯的任务可使用socket。固然Javascript脚本自己没法完成这个任务,因此须要调用外部程序来实现。这个外部程序能够用Python来写,我称之为slave.py,而Javascript脚本就是master.js,由于是master建立的slave进程。固然实际上slave并不听命于master,master反而要遵从slave从socket得到的指令。ios
这样一来,只须要写个驱动层,把API调用包装一下,经过socket传输到slave.py,再经过slave.py的stdout返回到master.js,再经过调用UI Automation API就实现了Python脚本的自动化测试。固然本文没有涉及不少细节实现问题,留给之后有时间再阐述。服务器
如下是简化的master.js示例代码:app
UIALogger.logMessage("Instruments started.")var target =UIATarget.localTarget();var app =target.frontMostApp();var window =app.mainWindow();var host =target.host();var screenshotPath = "screen";var python_path = host.performTaskWithPathArgumentsTimeout("/usr/bin/which", ['python'], 1).stdout.replace("\n", "");if (python_path == "") {
UIALogger.logError("python is not found.");
}else{while(1) {var result =host.performTaskWithPathArgumentsTimeout(
python_path,['InstrumentsSlave.py'], 30);var ins = ("" + result.stdout).split('\n');if (ins[0] == 'exitApp')break;switch (ins[0]) {case 'tap':var x = ins[1];var y = ins[2];
target.tap({x:x, y:y})break;case 'input':var s = ins[1];
app.keyboard().typeString(s)break;case 'captureScreen':
target.captureScreenWithName(screenshotPath);break;default:break;
}
}
}