本文次要介绍了字节 iOS 自动化测试驱动工具的摸索过程及实现原理
作者:字节跳动终端技术——陈友辉
一、背景
随着业务的扩张,单个 App 的性能越来越多,工程复杂度越来越高,每天 MR 可达上百次,代码变更可达上千处,航母级的 App 在这一点上更为严重。如何在频繁的代码变更中保障 App 品质,成了各个业务的痛点。靠传统的人工测试已无奈满足各业务的需要,咱们须要将更多的测试场景自动化。
自动化测试须要将人工交互行为变成自动化的原子操作。比方利用装置卸载、屏幕点拖拽及缩放、实体按键点击、设施信息获取、利用启停等等。这就须要一款工具来驱动 iOS 设施实现以上操作。这篇文章次要介绍字节 iOS 自动化测试驱动工具 bdc 的摸索过程及实现原理。
二、性能介绍
在介绍 bdc 的摸索过程及实现原理之前,先介绍一下 bdc 的能力:
三、摸索历程
晚期计划
在字节开始大规模建设自动化建设时,Android 曾经有较为欠缺的解决方案,包含其生态自带的驱动工具 adb 及开源的云真机治理平台 STF。但 iOS 在这方面绝对滞后,次要是 iOS 短少一款相似 adb 功能齐全且稳固的驱动工具。
晚期 iOS 采纳了 Facebook 开源的计划,Facebook 在驱动工具方面先后开源了 wda 与 idb,wda 反对 UI 交互操作,idb 反对利用治理,这在肯定水平上满足了咱们的需要,基于这套计划,搭建了第一个版本的自动化测试机架。
晚期的机架也很简略,机器的规模也不大 通过一段时间的实际,咱们遇到了以下几个问题
- wda 局部接口执行耗时较长,效率低下,无奈满足高频率调度的需要
- idb 很多命令只反对模拟器,对真机不够敌对,无奈满足咱们的性能扩大
- 命令执行失败率高,工具稳定性差,且出问题后难以排查
- 整套流程强依赖 Xcode 环境,规模化、自动化部署老本高,无奈应答上千台手机的部署
工具改进
UI 交互革新
为了解决上述问题,咱们联合 wda 的实现思路,实现了一个更高效稳固的 XCTest 工具。咱们对 XCTest 相干的接口进行了 review,并找到了 XCTest 实现跨过程调用最底层的接口。通过这些接口,能够间接调用 testmanagerd 过程。随后基于这些底层接口封装了一套新的接口,能够实现屏幕的点拖拽、实体按键点击、文本输出等操作。相比 wda,在执行速度和稳定性上取得大幅晋升。
testmanagerd 过程是一个开发者守护过程,在 iOS 设施开启开发者模式后,testmanagerd 过程的镜像会被挂载到 iOS 设施零碎的 Developer 目录,并被 launchd 过程启动。XCTest 应用苹果自带的 XPC 机制与 testmanagerd 进行通信,利用 NSXPCConnection,只需晓得服务的 id 即可建设通信,testmanagerd 服务的 id 可在其镜像文件里找到。镜像的门路位于:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport
解压镜像后,可在 Library/LaunchDeamons 目录下找到名为 com.apple.testmanagerd 的 plist 文件,关上后能够看到其 id 为 com.apple.testmanagerd(iOS14 后 id 有所变动)
设施交互工具
搞定 UI 交互后,接下来就须要找到能完满反对设施治理、利用治理、沙盒文件治理的计划。一开始咱们也是想基于 idb 进行优化,但随后发现 idb 外部应用了大量的 api,这些 api 绝大部分短少文档,优化老本较高,且这些公有 api 会随着 Xcode 版本的变动而更新,保护会很麻烦。所以放弃了 idb 转而寻找其余代替计划。
这时咱们发现了另一个开源实现 libimobiledevice,libimobiledevice 反对通过 USB 的形式与 iOS 设施进行通信,且反对利用装置卸载、设施信息获取、沙盒文件操作等性能。libimobiledevice 在应用体验上,操作简略,性能稳固。但毛病是性能无限,不能完全符合咱们的诉求,接下来咱们对 libimobiledevice 的实现原理进行了探索。
基于 USB 与 iOS 设施通信
苹果本身有一些 Mac App 须要通过 USB 跟 iOS 设施进行通信,比方 iTunes、XCode 及其套件等等。双端通信须要基于肯定的协定,通过 USB 通信须要应用 USB 协定,但 USB 协定具备肯定的局限性,间接应用老本较高。所以苹果在 USB 协定的根底上反对了 TCP 通信的能力,以此减小应用老本。
苹果通过 usbmuxd 来提供基于 USB 实现 TCP 通信的能力。usbmuxd 是一个守护过程,它在 USB 协定上实现了多路 TCP 连贯,能够让应用层无感知的基于 USB 通道进行 TCP 通信。
macOS 上的 usbmuxd 配置文件位于/Library/Apple/System/Library/LaunchDaemons
,关上后如下:
usbmuxd 的配置文件记录了加载属性、服务名称、可执行文件门路、socket 属性等信息。从下面的配置文件能够看到,usbmuxd 创立了一个 Unix 域的 socket。这个 socket 次要用于跟下层利用建设连贯,实现跨过程通信。基于 usbmuxd 进行网络通信的流程如下:
发现 iOS 设施零碎服务并实现调用
从上述 usbmuxd 的通信流程可知,想要跟 iOS 设施中的服务进行通信,只须要晓得具体服务的端口即可。那么服务端口该如何获取?个别有两种形式,一种是间接 hardcode,另一种是动静获取。iOS 设施外部的服务泛滥,如果全副 hardcode,其保护老本较高,且安全性及稳定性较低。如果是动静获取,那么获取的形式将成为另一个问题,因为动静获取自身也须要通信。
苹果则采纳了两者联合的形式。苹果在 iOS 零碎外部减少了一个 lockdownd 的守护过程,这个守护过程以 root 特权运行,具备拜访 iOS 零碎信息的能力,且运行在固定的端口。lockdownd 的配置文件如下,其门路位于 iOS 零碎的 /System/Library/LaunchDaemons/
目录。
由此能够看出,lockdownd 别离反对 Unix 域的 socket 与非 Unix 域的 socket,对于非 Unix 域的 socket,其监听的端口固定在62078。
当 PC 端想要跟 iOS 设施中的某个服务进行通信时,先通过 lockdownd 查找对应服务的端口,而后再跟对应的服务建设 socket 连贯,其流程如下:
libimobiledevice 就是利用以上流程对 iOS 设施中的服务进行了调用,比方在操作沙盒文件时,就是调用了 iOS 设施中的 afc、house_arrest 服务。
服务类型
搞清楚了调用流程,那么 iOS 设施中都有哪些服务呢?iOS 零碎服务次要分为两类:一类是 debug 相干服务,关上开发者选项后才具备相应服务。另一类是非 debug 服务,默认都具备。
debug 相干服务的配置文件及可执行文件都被打包放在了 Xcode 中,位于 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/
目录,当 iOS 设施连贯 Xcode 时,Xcode 会主动将此目录下对应的 DeveloperDiskImage 挂载到 iOS 零碎中。其蕴含的服务如下: 上述提到的 testmanagerd 就位于其中。
非 debug 服务位于 iOS 零碎的 /System/Library/LaunchDaemons
目录。通过越狱后,咱们能够查看 /System/Library/LaunchDaemons
目录下的内容,以下是局部服务的截图,能够看到,服务十分之多。
能力扩大
搞清楚 libimobiledevice 实现原理后,基于这个思路,咱们又自行摸索了其余一些服务的能力,这其中就包含 Xcode 相干的服务。Xcode 为开发者提供了业余、稳固的工具集,而 Xcode 的工具集也是利用以上机制与 iOS 设施进行通信。基于 Xcode 的能力,咱们实现了 Trace 采集、设施利用治理等性能。
反对 Linux
工具的问题解决了,接下来就是部署的问题。咱们须要面对上千台 iOS 设施接入及每天上万次的服务调度,且设施之间的环境须要互相隔离,互不烦扰。所以在设施及工具的部署上须要简略、高效。比拟好的解决方案是采纳 docker 部署,每台设施及其对应的驱动工具都用 docker 分来到,这样能做到环境隔离,且部署简略。但 Mac 对 docker 的反对并不那么敌对,且咱们的工具自身依赖 Xcode 环境。
既然 Mac 对 docker 的反对不敌对,那咱们是否能解脱对 Mac 的依赖,将设施及工具部署在 Linux 上。顺着这个思路,咱们开始了对工具的第二次革新。
反对 XCTest 启动
工具对 Mac 的依赖次要来源于 XCTest 工具的启动,相似于 wda。咱们将 XCTest 的接口封装在了一个一般的 App 里,而后在这个一般的 App 里搭建一个 websocket server,这样就能够通过网络与这个 App 通信,实现 XCTest API 的调用。但通过尝试后,发现一般的 App 调用 XCTest API 并不会产生预期的成果。所以还须要一些非凡的操作能力使一般 App 具备调用 XCTest API 的能力。
咱们从失常的 XCTest-Runner 动手摸索其启动流程。以 home 键的点击办法为切入点,通过 LLDB 追踪 testmanagerd 过程中接口的调用流程,发现了如下要害的接口:
_IDE_authorizeTestSessionWithProcessID:
剖析后发现,testmanagerd 会保护一个过程白名单,只有将 App 的过程 ID 加到这个白名单里,这个 App 才具备调用 XCTest API 的能力。而上述注册白名单的接口则能够通过后面提到的 lockdownd 的形式调用。基于此,咱们实现了解脱对 Mac 环境的依赖,在 Linux 实现了 docker 化部署。
四、运行成果
bdc 工具上线已有一年多。目前撑持了公司自动化测试平台上千台 iOS 设施每日上万次的设施调度及测试工作执行。自动化测试平台涵盖了稳定性、UI、性能、单元测试等多项测试能力,服务公司上百个业务。
设施机架从原有的简陋设施已降级为寰球机房,服务于寰球业务。
🔥 火山引擎 APMPlus 利用性能监控是火山引擎利用开发套件 MARS 下的性能监控产品。咱们通过先进的数据采集与监控技术,为企业提供全链路的利用性能监控服务,助力企业晋升异样问题排查与解决的效率。目前咱们面向中小企业特地推出「APMPlus 利用性能监控企业助力口头 」,为中小企业提供利用性能监控免费资源包。当初申请,有机会取得60 天 收费性能监控服务,最高可享 6000 万 条事件量。
👉 点击这里,立刻申请