基于Fastbot的移动端自动化测试方案

语言: CN / TW / HK

背景介绍

自动测试生成 ATG

自动测试生成 ATG(Automated Testing Generation)技术,也叫 AIG(Automated Input Generation)技术。传统的自动化方式,比如录制与回放(Record & Replay),依赖于测试人员编写测试脚本。同时,跟随着测试需求的改变,测试人员需要耗费一定的时间维护和调整相应的测试脚本。与录制回放的方式相比,将测试活动依赖的通用服务进行抽象,依靠自动的方式生成测试活动需要的操作,能较大程度减少测试脚本的编写与维护工作量。

目前,典型的 ATG 技术有:

  • 程序分析;(Code-Based Testing);
  • 基于模型的测试生成(Model-Based-Testing);
  • 组合测试(Combinatorial Testing);
  • 基于搜索的测试生成(Search-Based-Testing), Facebook 的 Sapienz;
  • 自适应随机测试(Adaptive Random Testing)。

市面测试工具

image-20220509103432286

image-20220509103449644

表 1 列举了目前市面上几款常见的 iOS UI 自动化框架。

整体上可分三类,

1)App 源码插桩:通过插桩 SDK 获取宿主页面控件树和进程内注入可执行操作,插桩方式执行速度快,但也有弊端,拙劣的 SDK 可能对宿主 App 有不良影响,比如稳定性变差了,此外进程内注入方式是无法操作一个系统级弹窗的。

2)WDA 私有接口:这种方式的好处是无需插桩,也是目前主流的 iOS UI 自动化方案,但是往往使用了私有接口就一定带来兼容问题,其次私有接口获取控件树的性能有时也令人堪忧。

3)图像识别结合 WDA 私有接口:基于此自动化能力完全取决于图像的能力,另外 2 中拥有的优缺点它也同样拥有。

image-20220509103548453

表 2 是目前市面上几款相对较好的 iOS 端稳定性 Monkey 测试工具。

总结来说基本都是基于 XCTest 和 WDA 来实现的,但是普遍问题是更新维护不及时,甚至是已经停止维护很久。其工具研发面临的首要问题是对 iOS 新版兼容开发成本巨大。

特别是涉及 WDA(WebDriverAgent,提供了某些跨进程 App 调度和获取控件树的能力)私有接口的兼容,往往面临等待 Facebook 解决 WDA 的兼容后才能着手展开。

但现实也很不幸,Facebook 目前已经放弃了对 WDA 的后续兼容,转向 IDB 研发(iOS Development Bridge,类似于安卓中的 adb 工具,但在真机上存在稳定性问题尚无法完全替代 WDA),WDA 现在则由 Appium 以社区形式接手继续迭代。

Fastbot 方案简述

Fastbot的总体分为两部分:

  • 服务端:负责测试模型搭建,动作决策,指令下发。
  • 客户端:负责GUI信息上报,处理服务端下发的动作。

客户端与服务端会分别创建一个Agent,通过Socket通道进行通信。

测试流程:

  1. 服务端Agent将客户端Agent上传的GUI信息进行封装,生成State节点。
  2. 服务端Agent再通过当前State信息,按照分配好的算法,与任务模型交互,作出Action决策。
  3. 服务端Agent将Action决策发回客户端Agent,客户端执行Action。

在步骤2中,服务端会判断是否发生了崩溃,覆盖率信息,当前节点的路径记录等多种信息,用于实现数据分析,路径回放和测试生成。

崩溃查看

当Fastbot在测试过程中发生了崩溃时,需要从测试设备的Crash logs中去获取崩溃信息。

Fastbot环境配置

安装Xcode,Cocoapods

shell sudo gem install cocoapods -v=1.8.1

初始化项目

拉取仓库和依赖

shell git clone https://github.com/bytedance/Fastbot_iOS.git cd Fastbot_iOS && cd Fastbot-iOS && pod install --repo-update

设置证书

  1. 勾选Automatically manage signing,开启自动签名
  2. 修改bundle Id为唯一id,路径 Target -> BuildSettings ->Product Bundle Identifier
  3. 在Xcode中登陆开发者账号

测试设备配置

  1. 连接手机到mac,信任测试手机。

  2. 执行单元测试中的 FatbotRunner -> testPingNetwork,完成测试用例Pass,期间会安装一个App(如FastbotRunner-Runner)

可能需要解决的问题:

  1. 需要信任App的证书
  2. 等待获取网络权限,手动打开App,等待几秒时间,切回到桌面,此时弹出是否开启网络权限的弹窗,选择开启。该操作重复,直到testPingNetwork用例Pass。

By tapping FastbotRunner on the device, the screen of the device would go black for about one minute. During the black screen interval, users should press the home button on the device to go back to the main screen. Wait patiently until the network setting dialog window pops up. Users should allow the pop up request in order to continue.

通过点击设备上的FastbotRunner,设备的屏幕会变黑约一分钟。在黑屏间隔时间内,用户应按下设备上的home键返回主屏幕。请耐心等待弹出网络设置对话框。为了继续,用户应该允许弹出请求。

开始测试

  1. 将被测试的App安装至测试手机上。
  2. 输入设备密码,启用UI自动化测试(每次测试只会出现一次)。
  3. 在运行Scheme中添加测试参数(Test-Debug阶段)。

| 字段 | 说明 | 示例 | | --------- | ------------------------------------------------------------ | ------------------------------- | | BUNDLEID | 被测试App的 Bundle ID | com.xxx.xxx | | duration | 测试时长,单位分钟 | 240 | | launchenv | 用于传递测试App的环境变量,一般为空,或者以 ':'分割的key=value形式 | isAutoTestUI=1:channel=AutoTest | | throttle | 操作间隔,单位毫秒 | 300 |

  1. 执行 FastbotRunner -> testFastbot,被测试App将被唤起。如果没有唤起,在等待时手动唤起被测试的App。

Shell启动

```shell

(如果启动Scheme设置中的启动参数被更改则需还原),可根据实际情况使用build-for-testing test-without-building,id为设备的udid

BUNDLEID=com.xxx.xxx duration=240 throttle=300 xcodebuild test -workspace Fastbot-iOS.xcworkspace -scheme FastbotRunner -configuration Release -destination 'platform=iOS,id=00008101-000318213123451E' -only-testing:FastbotRunner/FastbotRunner/testFastbot ```

Stub 模式

fastbot_stub注入到被测试的App中。该库可以捕获App在测试过程中的GUI结构信息。可以使用更多自定义的功能(如hook callback、cut View),还有防止某些View被点击,自定义ViewControllers等。

  1. 将fastbot_stub 通过pod 方式集成进被测试的App
  2. 取消代码注释:[fastbot_native addUIInterruptionMonitor: ...]; in FastbotRunner.m

  3. 修改FatbotRunner的Scheme中参数

    | key | sample | | --------- | ------------- | | launchenv | stubPort=9797 | | dataport | 9797 |

  4. 先启动被测试App,让GCDWebServer启动。

  5. 再使用Shell开启FastbotRunner

工具

libimobiledevice

| 实用工具 | 描述 | | -------------------------- | ------------------------------------------- | | idevice_id | 列出给定设备的附加设备或打印设备名称 | | idevicebackup | 为设备创建或恢复备份(旧版) | | idevicebackup2 | 为运行 iOS 4 或更高版本的设备创建或恢复备份 | | idevicebtlogger | 从设备捕获蓝牙HCI流量(需要日志配置文件) | | idevicecrashreport | 从设备检索崩溃报告 | | idevicedate | 显示当前日期或在设备上设置 | | idevicedebug | 与设备的调试服务器服务交互 | | idevicedebugserverproxy | 从设备代理调试服务器连接进行远程调试 | | idevicediagnostics | 与设备的诊断接口交互 | | ideviceenterrecovery | 让设备进入恢复模式 | | ideviceimagemounter | 在设备上挂载磁盘映像 | | ideviceinfo | 显示有关已连接设备的信息 | | idevicename | 显示或设置设备名称 | | idevicenotificationproxy | 在设备上发布或观察通知 | | idevicepair | 管理主机与设备和usbmuxd的配对 | | ideviceprovision | 管理设备上的预置描述文件 | | idevicescreenshot | 从连接的设备获取屏幕截图 | | idevicesetlocation | 模拟设备上的位置 | | idevicesyslog | 连接设备的中继系统 |

参考链接

Fastbot Github仓库

Fastbot:行进中的智能 Monkey

奔跑吧!智能Monkey之Fastbot跨平台

应用性能监控全链路版