本文首要介绍了字节 iOS 自动化测验驱动东西的探求进程及完成原理

作者:字节跳动终端技术——陈友辉

一、布景

跟着业务的扩张,单个 App 的功用越来越多,工程复杂度越来越高,每天MR可达上百次,代码改变可达上千处,航母级的 App 在这一点上更为严重。如何在频频的代码改变中保障App质量,成了各个业务的痛点。靠传统的人工测验已无法满意各业务的需求,咱们需求将更多的测验场景自动化。

自动化测验需求将人工交互行为变成自动化的原子操作。比方运用装置卸载、屏幕点拖拽及缩放、实体按键点击、设备信息获取、运用启停等等。这就需求一款东西来驱动 iOS 设备完结以上操作。这篇文章首要介绍字节 iOS 自动化测验驱动东西 bdc 的探求进程及完成原理。

iOS自动化测试驱动工具探索

二、功用介绍

在介绍 bdc 的探求进程及完成原理之前,先介绍一下 bdc 的才能:

iOS自动化测试驱动工具探索

三、探求进程

前期计划

在字节开端大规模建造自动化建造时,Android 已经有较为完善的处理计划,包含其生态自带的驱动东西 adb 及开源的云真机办理渠道 STF。但 iOS 在这方面相对滞后,首要是 iOS 短少一款相似 adb 功用完全且安稳的驱动东西。

前期 iOS 选用了 Facebook 开源的计划,Facebook 在驱动东西方面先后开源了 wda 与 idb,wda 支撑 UI 交互操作,idb 支撑运用办理,这在必定程度上满意了咱们的需求,根据这套计划,搭建了第一个版别的自动化测验机架。

iOS自动化测试驱动工具探索

前期的机架也很简单,机器的规模也不大

iOS自动化测试驱动工具探索
经过一段时间的实践,咱们遇到了以下几个问题

  • 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 有所变动)

iOS自动化测试驱动工具探索

设备交互东西

搞定 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,翻开后如下:

iOS自动化测试驱动工具探索

usbmuxd 的配置文件记录了加载特点、服务称号、可履行文件途径、socket 特点等信息。从上面的配置文件能够看到,usbmuxd 创建了一个 Unix 域的 socket。这个 socket 首要用于跟上层运用树立衔接,完成跨进程通讯。根据 usbmuxd 进行网络通讯的流程如下:

iOS自动化测试驱动工具探索

发现iOS设备体系服务并完结调用

从上述 usbmuxd 的通讯流程可知,想要跟iOS设备中的服务进行通讯,只需求知道详细服务的端口即可。那么服务端口该如何获取?一般有两种办法,一种是直接hardcode,另一种是动态获取。iOS设备内部的服务很多,如果悉数 hardcode,其保护本钱较高,且安全性及安稳性较低。如果是动态获取,那么获取的办法将成为另一个问题,由于动态获取自身也需求通讯。

苹果则选用了两者结合的办法。苹果在iOS体系内部增加了一个 lockdownd 的看护进程,这个看护进程以 root 特权运转,具有访问 iOS 体系信息的才能,且运转在固定的端口。lockdownd 的配置文件如下,其途径坐落 iOS 体系的/System/Library/LaunchDaemons/目录。

iOS自动化测试驱动工具探索

由此能够看出,lockdownd 别离支撑 Unix 域的 socket 与非 Unix 域的 socket,对于非 Unix 域的socket,其监听的端口固定在62078

当 PC 端想要跟 iOS 设备中的某个服务进行通讯时,先经过 lockdownd 查找对应服务的端口,然后再跟对应的服务树立 socket 衔接,其流程如下:

iOS自动化测试驱动工具探索

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 体系中。其包含的服务如下:

iOS自动化测试驱动工具探索

上述说到的 testmanagerd 就坐落其中。

非debug服务坐落iOS体系的/System/Library/LaunchDaemons目录。经过越狱后,咱们能够检查/System/Library/LaunchDaemons目录下的内容,以下是部分服务的截图,能够看到,服务非常之多。

iOS自动化测试驱动工具探索

才能扩展

搞清楚 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 化布置。

iOS自动化测试驱动工具探索

四、运转作用

bdc 东西上线已有一年多。现在支撑了公司自动化测验渠道上千台 iOS 设备每日上万次的设备调度及测验任务履行。自动化测验渠道涵盖了安稳性、UI、功能、单元测验等多项测验才能,服务公司上百个业务。

设备机架从原有的简陋设备已晋级为全球机房,服务于全球业务。

iOS自动化测试驱动工具探索


火山引擎 APMPlus 运用功能监控是火山引擎运用开发套件 MARS 下的功能监控产品。咱们经过先进的数据收集与监控技术,为企业供给全链路的运用功能监控服务,助力企业提高异常问题排查与处理的效率。现在咱们面向中小企业特别推出「APMPlus 运用功能监控企业助力行动」,为中小企业供给运用功能监控免费资源包。现在请求,有时机获得60天免费功能监控服务,最高可享6000万条事情量。

点击这里,当即请求