​ ​本人不是专业干测试的,只是一只小小的前端弱鸡,前一阵子领导让人研究一下 “UI 自动化”,这是我第一次听到这个名词,但是掉了 “测试” 两个字,我踏马半天不知道是干啥的。

​ ​百度一下才知道是自动化测试,整个 UI 自动化,这样没次版本发布,都不需要人工去回归了,跑一套脚本就 OK,怠惰势力登场。

​ ​我要找的是同时支持 iOS 和 Andorid 的,最开始接触了 Appium,网上都说好,好是好可惜我生错了年代,升级了 XCode8,只用过 iOS10 的我兴冲冲地去安装 Appium,npm 安装时各种失败,下了客户端不会用,文档还时英文的,又花了几天折腾 npm 安装,安装好了测试例子跑了几下挂了。于是在 GitHub 上用机翻的英文问作者,大神说没有了 UIAutomation,对 iOS10 支持不好。于是我就放弃了,在 TesterHome 上遇到了 Macaca,虽然 Macaca 的官网也和我一样崇洋媚外用了英文(一个中文都没有的那种),但是别人的网站的外观甩了 Appium 几条街,还贴心地配上了短小的演示视频,格外适合我这种天真的小白。

​ ​然后我就和 Appium 说拜拜,安装了 Macaca,命令一敲,碰上 WebView 就挂(我要测试就是挂载在 WebView 上的 Hybrid 页面),给作者提 bug,大神甩了我一条链接(我估计他都没看我描述的问题,我写的那么幸苦那么认真),进去没有我的问题,徐大就让你升级 ios-webkit-debug-proxy。试了很久都没有解决,只好自己动手,下面说说坑一。

坑一:ios-webkit-debug-proxy 和 Macaca 谁更厉害?

ios-webkit-debug-proxy 隶属的组织是 Google,Google 说:我永远是你们的大爷。所以他就给所有的 Simulator 的 deviceId 都用个"Simulator",因此当我启动模拟器,在命令行输入:
ios_webkit_debug_proxy
​ ​然后访问 localhost:9221/json ,你看到的都是这个模拟器设备数组:

[{ 
"deviceId": "SIMULATOR", 
"deviceName": "SIMULATOR",
"url": "localhost:9222"
}]

​ ​当你连上真机,待遇马上就不一样了:

[{
   "deviceId": "SIMULATOR",
   "deviceName": "SIMULATOR",
   "url": "localhost:9222"
},{
   "deviceId": "a11a05063f40bf7a730800045e7dbd1c76ea5121",
   "deviceName": "不好用的iPhone",
   "url": "localhost:9223"
}]

​ ​ios_webkit_debug_proxy 明显长着资本家丑恶的嘴脸,这些模拟器我都不承认你是有 deviceId 的 iPhone,不管你是跑着疯 5 疯 7 的模拟器,我都叫你模拟器。而 Macaca 比较耿直,从不把模拟器当模拟器看,就像老板从来不把员工当人看,就用编号给你起了个名字,所以就有 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX 这么长的编号。
当我们要从 Native 切换到 WebView 时,呵呵,你的脚本就挂了:

>>     #4 should display webview (8584ms)
ios_webkit_debug_proxy path: /usr/local/bin/ios_webkit_debug_proxy
  Error: Device: D9C8ACB9-0A5E-42A2-92AA-A52243429AAD does not exist.
      at request.get.then.then.devices (/Users/Cononico/.nvm/versions/node/v6.9.1/lib/node_modules/macaca-ios/node_modules/remote-debugger/lib/remote-debugger.js:39:17)
      at tryCatcher (/Users/Cononico/.nvm/versions/node/v6.9.1/lib/node_modules/macaca-ios/node_modules/bluebird/js/main/util.js:26:23)
      at Promise._settlePromiseFromHandler (/Users/Cononico/.nvm/versions/node/v6.9.1/lib/node_modules/macaca-ios/node_modules/bluebird/js/main/promise.js:510:31)
      at Promise._settlePromiseAt (/Users/Cononico/.nvm/versions/node/v6.9.1/lib/node_modules/macaca-ios/node_modules/bluebird/js/main/promise.js:584:18)
      at Promise._settlePromises (/Users/Cononico/.nvm/versions/node/v6.9.1/lib/node_modules/macaca-ios/node_modules/bluebird/js/main/promise.js:700:14)
      at Async._drainQueue (/Users/Cononico/.nvm/versions/node/v6.9.1/lib/node_modules/macaca-ios/node_modules/bluebird/js/main/async.js:123:16)
      at Async._drainQueues (/Users/Cononico/.nvm/versions/node/v6.9.1/lib/node_modules/macaca-ios/node_modules/bluebird/js/main/async.js:133:10)
      at Immediate.Async.drainQueues (/Users/Cononico/.nvm/versions/node/v6.9.1/lib/node_modules/macaca-ios/node_modules/bluebird/js/main/async.js:15:14)
      at runCallback (timers.js:637:20)
      at tryOnImmediate (timers.js:610:5)
      at processImmediate [as _immediateCallback] (timers.js:582:5)
>>

​ ​ios_webkit_debug_proxy 非要叫它模拟器,Macaca 非要叫编号,倒霉的就我这样的无辜群众。不管谁对谁错,反正没人解决我的问题,最后只好自己动手改改代码了,在全局安装的 Macaca-ios 中加点佐料,路径大概是
xxxxxx/macaca-ios/node_modules/remote-debugger/lib/remote-debugger.js
第 34 行加上:

if(devices[0].deviceId === 'SIMULATOR') {
    devices[0].deviceId = this.deviceId;
}

​ ​管你那多,我只有一个模拟器(神特么老板给你搞十几台 iPhone 让你个傻屌测试),这样也就够用了。

坑二:论官方实例的严肃性。
Macaca 官方的例子多久没更新了,小看即可,懂怎么写脚本就行了,不要抄他的例子,因为例子也会挂。最后 Macaca-wd 的文档有点简陋:贴出方法名,用四五个单词解释,最后甩出一个链接直接去看 WebDriver 的解释了,看不懂就是你的水平问题了,另外 WebDriver 根本就不会教你怎么用这个方法。总而言之,都是你的问题,谁让你弱鸡去哪都被踩。

坑三:理想与现实:
理想的是你跑作者的例子,而实际到了我司,情况大不一样。作为一个正规渠道发布的 APP,当你第一次打开,会提醒你允许本 APP 联网吗,要本 APP 推送消息吗,你得用脚本去同意;然后就是每个 APP 都要的,进去后的滑动页面,展示这个 APP 如何牛逼如何有优势,你得用脚本一个个划过去;好不容易进了 APP,迎面而来就是双十一的活动弹框,没错,你还是得用脚本去关......到这里你就会发现进入你要测试的地方比你的测试代码写的还多。

小结:
Macaca 是我用过最好用的 UI 自动化工具(虽然我只用过两个),支持 PC,iOS,Android,用起来也是一颗 Promise 一股脑走下去。如果你想一次性测试多个平台,可以写分别几个不同平台的测试用例,使用 Generator 函数 next() 下去。
重要:作者别打我!!!!


↙↙↙阅读原文可查看相关链接,并与作者交流