总篇20篇 2018年第20篇
背景
汽车之家移动业务发展越来越快,研发团队规模越来越大,在研发、测试阶段对测试设备的资源和成本需求也越来越强烈,测试过程中都很难做到多机型。怎么样合理、高效利用这些测试手机资源,是摆在我们面前的一道难题。
现状
目前的解决方案
1.部门内部采购热门机型
2.部门之间互相借用设备
3.冷门机型、操作系统测试暂不覆盖
4.云真机租用设备进行
这些方案在成本、测试周期及效率、用户体验上都有一定的弊端
目标和方案
为了解决这些问题,我们调研了业内的解决方案,在Android端有开源的OpenSTF、百度的MTC、Testin的云真机等等,但是在iOS端,由于iOS平台相对封闭,目前只有某些商业平台的云真机服务且收费很高。基于以上问题汽车之家测试团队开始自研iOS真机平台。我们的目标是通过提供稳定的7*24 iOS云真机服务来提升设备的利用率。
用户通过浏览器实现远程iOS设备的查看和操作,示意图如下:
参考Android相对开源且成熟的云真机平台实现,移植到iOS端,我们面临的三个主要问题:
1. 如何实现远程真机画面实时地在用户端流畅的显示。(要求帧率较高)
2. 如何将用户端的操作实时作用于远程真机。(要求延迟较低)
3. 安装APP程序包和系统日志获取
为了解决这几个问题,我们调研了多个目前应用较多的技术方案,由于我们的目的是模拟用户真实的使用环境,防止测试环境失真,因此不考虑越狱的解决方案。
将iOS设备画面传递给前端用户的远程实时画面回传,主要方法有两种:
iOS设备截屏传输
iOS设备截屏使用开源的libimobiledevice工具库,它实现了iOS设备的信息获取(ideviceinfo)、日志获取(idevicesyslog)、屏幕截图(idevicescreenshot)、安装APP包(ideviceinstaller)等功能,缺点是截图I/O效率不高,最高只能实现每秒2~5帧的屏幕截图。
获取iOS视频流传输
Mac系统中自带的QuickTime-Player可以对通过USB连接的iOS设备进行流畅的屏幕录制,其原理是使用苹果的AVFoundation和CoreMediaIO库实现iOS设备视频流获取,但是QuickTime-Player是一个封闭的桌面软件无法被集成。
OpenSTF的开源项目iOS-minicap利用AVFoundation和CoreMediaIO库实现视频流获取,使用turbojpeg库实现图像的二进制转换,再通过socket将图像数据流转发到相应端口,此方法传输的速度很快且延迟也很低,可以实现每秒20帧(20FPS)以上流畅的画面传输。
满足每秒20帧以上的画面人眼即视为流畅,考虑使用体验我们选择了视频流传输获取的解决方案iOS-minicap。
将前端对手机进行的点击、拖拽、输入文字等指令传递给远程iOS设备并实现相应操作的远程实时操控,其事件驱动本质与iOS自动化驱动事件类似,我们调研了比较常用的iOS自动化的驱动,主要有:
苹果官方提供的XCTest和XCUITest
Facebook的开源项目WebDriverAgent(以下简称WDA)
开源自动化测试工具Appium
阿里巴巴的开源项目Macaca的XCTestWD
经过调研分析底层实现原理,Appium在iOS自动化测试中使用了WDA作为事件驱动,而WDA底层使用的是苹果的XCTest以及XCUITest,Macaca的XCTestWD的实现原理与WDA类似。远程真机不需要集成自动化测试,所以我们选择WDA作为远程操控事件驱动。
WDA实现了一个后台常驻的HTTPServer,通过xcode的test方式启动WDARunner,接收包含操作指令的HTTP请求,调用XCUITest相应方法操作手机(本质是进行iOS的UI测试),以此实现真机的远程操控。
但在实际应用中,我们的网络无法直接访问iOS设备端建立的HTTPServer,要解决这个问题,需要实现从设备所连接的Mac主机与iOS设备的数据转发,解决方案有两种:
可以集成在APP中实现iOS与Mac连接的开源方案peertalk
libimobiledevice的开源工具iproxy。
两种方式都是基于苹果usbmuxd(Mac与iOS设备连接的USB驱动)服务的方案,将USB通信抽象为TCP通信。
peertalk是最早实现iOS与Mac连接的开源方案,但是早已停止更新,部署复杂(iOSAPP与Mac两端都需要部署),且需要修改大量的源码,集成难度较高;而iproxy是libimobiledevice实现了苹果usbmuxd服务的开源工具,仅需要部署在Mac端,使用方便,所以我们选择iproxy实现协议转发。
安装APP程序包和系统日志获取目前只有libimobiledevice的ideviceinstaller(安装APP)和idevicesyslog(系统日志获取)。
基于以上,我们设计了iOS远程真机实现方案,示意图如下:
根据业务场景需要,多个用户同时访问多台设备,并且需要将被占用的设备设置不可用,因此我们设计了可以实现业务需求的项目的整体架构。
项目整体架构如下图:
系统总体属于B/S结构,分为几个模块。
Web前端:用户使用的浏览器,实现查询iOS设备状态、发送连接请求,根据请求返回的Mac设备信息与相应的Mac设备进行Websocket直连。
Django后台:用户身份验证,查询Redis中的iOS设备信息及占用状态,展示给前端,接收前端的iOS连接请求转发至统一调度平台,将统一调度平台返回的Mac设备信息发送回Web前端。
统一调度平台:接收Django后台的连接请求,通过查询Redis中Mac设备信息,连接相应Mac设备中的iOS设备调度程序,发送连接请求,并将iOS设备调度程序返回的结果发送回Django后台。
iOS设备调度:每一个连接iOS设备的Mac主机都运行一个iOS设备调度程序,它收集Mac设备上连接的iOS设备信息并上传至Redis,通过RPC与统一调度平台连接接收请求,在用户使用时,与Web前端进行Websocket直连。
遇到的问题
我们按照这个结构进行项目搭建并进行了测试,但发现了一些问题:
WDA点击操作无法进行敏感权限操作(如删除APP、授权信任证书等)
WDA实现的滑动缓慢且延迟较高
iOS-minicap存在帧率不稳定、画面卡死现象
WDA与iOS-minicap启动冲突导致启动失败
针对前两个问题,我们对WDA项目代码进行了优化,使用了苹果私有API,私有API的头文件可以使用RuntimeBrowser等iOS逆向工具导出。优化后实现了:
提升权限的点击操作
毫秒级的点击响应
200ms以内延迟的滑动响应
稳定20+FPS的画面输出
① 重写了点击(Tap)方法
点击方法使用了XCEventGenerator私有API,输入点坐标即可实现点击操作,长按(TapAndHold)只需在此基础上增加持续时间(duration)参数即可,解决了原有方法中敏感操作的权限问题,也减少了延迟,实现毫秒级的响应。
② 重写了滑动(Drag)方法
滑动方法同样使用了XCEventGenerator私有API,输入起点、终点坐标与持续时间即可实现滑动操作。此方法可以将滑动延迟控制在200ms以内,大大提升了滑动操作的流畅度。
③ iOS-minicap的实现方法中并没有控制获取视频流转图片发送至iOS-minicap端口的帧率限制,导致Mac设备实现的帧率不稳定,在通过Websocket转发时会产生时快时慢的卡顿现象以及阻塞卡死现象,我们在代码中加入了一个40毫秒的timer,保证帧率不高于25帧,实现了高帧率(20-25FPS)的稳定画面输出。
④ WDA的启动与iOS-minicap启动都会占用xcodebuild资源,同时启动会引起冲突并且导致WDA的启动失败,我们将WDA的启动延迟,在iOS设备调度程序中加入一个控制WDA启动的全局变量,在iOS-minicap启动完成并发送第一帧图片帧之后再启动WDA,解决冲突问题。
与此同时,我们还实现了日志流输出、字符输入/清除等功能。
实现的效果如下图
效果图一:
效果图二:
后
续
规
划
我们计划继续扩展产品功能,比如优化log日志展示,IDE远程调试(正在开发中),iOS可视化自动化测试、设备集群、多屏操作、提供服务接口等,我们也会不断的迭代版本、打磨产品,提供更好的使用体验。
最后欢迎有兴趣的同学与我联系,共同探讨共同进步,也欢迎同学们参与到我们的项目。
更多精彩技术文章,欢迎大家访问汽车之家系统平台团队博客http://autohomeops.corpautohome.com