自动化工具 关于客户端自动化测试的思考和经验总结

Bodhisatan · 2021年01月29日 · 最后由 Bodhisatan 回复于 2021年01月30日 · 10442 次阅读

2020 年的 1 月 15 号,我入职了百度,成了一名测试开发实习生,到现在为止,也已经有整整一年的时间了。

这一年发生了很多事,因为疫情原因在出租屋里吃了一个月的泡面,因为不返校而得以一直实习,先是在百度,然后是在字节。一年前的我只有后端开发的经验,对测试领域一无所知,误打误撞进了客户端测试的领域,并且一直做了下来。一年,和各位大佬比起来不过是刚刚入门,但是经历了一些之后也算是有所思考和沉淀吧。下面就谈一谈我经过一年的工作,对于客户端自动化测试手段的思考。

UI 自动化

UI 自动化,这几乎是每一个客户端方向的测试工程师在学习或者团队内发展自动化测试的时候的第一个方向。大家提到自动化测试,一般而言,如果是客户端领域,指的就是 UI 自动化。在我刚入职百度的时候,我的方向就是双端的 UI 自动化。

什么是 UI 自动化

UI 自动化,就是将用户的行为通过 “自动化测试框架” 进行模拟,例如模拟划动、模拟点击,将一些测试场景抽象出来进行自动化测试,以此达到节约人力的作用。目前市面上的自动化测试框架非常多,例如appiumtotoroQTAuiauia2等。一些大厂基于不同的侧重点也会进行自己的自动化框架的研发,比如携程基于行为驱动(BDD)的自动化测试,网易提出的用图片就能编写 case 的Airtest,腾讯从稳定性和多端支持角度提出的QTA等。不同的框架出发点不一样,有的是为了稳定性,有的是为了编写时上手的简单性,有的是为了可扩展性,但是框架的原理大同小异,可以认为一个完整的 UI 自动化框架一般由两部分组成:UI 驱动设备驱动

UI 驱动用来执行对元素的操作,比如查找元素、点击元素,设备驱动用来执行对设备的操作,比如冷启 app、关机等。设备驱动的话安卓端的开源方案有adb,iOS 端的开源方案有 facebook 的wdaidb,一些公司也会进行自己的设备驱动的开发,比如字节自研的BDC。UI 驱动的话,主要思路有两种,一种是注入式,一种是非注入式。像上手最简单的Appium采用的就是非注入式方案,查找和操作 UI 是从 App 进程外对 App 进行操作的。非注入式的 UI 驱动有:安卓端的UIA,iOS 端的InstrumentationXCUITest等。腾讯的QTA和字节的Shoots采用的就是注入式方案,对 app 进行重打包,往包里注入一个 server,在 app 启动的时候,启动一个对应的网络服务,通过这个网络服务提供测试接口。

因此,从 UI 驱动这个角度出发,可以将自动化框架分成两大类:注入式、非注入式,那么这两种各有什么优劣势呢?最大的不同点在于稳定性性能

  • 稳定性:记得刚用 Appium 的时候,测试机是一台 vivo 低端机,case 编写好之后运行的时候,稳定性非常差,首先是定位元素很慢(这和设备性能也有关系),然后是经常跑着跑着,从一个 case 开始,后面的全部 case 都失败了,然后查了日志才发现,vivo 魔改 OS,把耗电高的进程——也就是测试服务的进程给杀了。但是如果 UI 驱动是注入式的,那么测试服务和 App 本身就会 “同生共死”,只要 App 进程不死,测试进程也不会死,同时注入式的 UI 驱动也会极大增大元素定位的速度
  • 性能:因为测试服务是注入进 App 进程里的,所以或多或少都会影响 App 本身运行的速度,所以做性能评测时,要么保证框架对性能的影响有限,要么采用非注入式框架

UI 自动化的用处

UI 自动化不光光是 UI 自动化,可以以 UI 自动化为入手点,将客户端测试的很多方面通过自动化落地,比如埋点自动化测试、性能自动化测试等。

  • 功能回归测试:这是 UI 自动化最基础的用途,因为一般新功能的话手工回归更稳妥,所以重复性高的回归 case 采用自动化测试更为合适,可以将功能回归测试放在持续集成流程里,每出一个新包/每监听到一个新 push 就执行一遍,保证新增代码不影响旧功能或者核心功能

  • 埋点测试:埋点上报的本质是发送 http 请求,埋点测试也是进入到某个 App 场景后进行埋点数据校验,那么可以利用一些技术手段,劫持 App 发送的埋点数据,然后通过 json schema 进行自动化校验。json schema 可以自己编写,也可以在录制 case 的时候进行生成

  • 性能测试:有时候需要把自己产品的一些核心场景与竞品横向对比,做性能评测。性能主要有以下几个指标:耗时、cpu、fps 等。如果不用自动化手段,需要手动录屏,然后手动拆帧获得耗时数据,安卓端通过 adb 命令获得 cpu、fps 等数据,iOS 则更为复杂。用自动化可以实现自动录屏,自动分帧,自动选取开始帧结束帧计算耗时,还可以集成一些工具,自动获取 cpu、fps 等信息。

  • 服务端接口防劣化:假如有这样一个场景——一个服务端接口因为种种原因挂了,导致线上功能异常或者页面白屏,此时一般只能通过用户反馈或者服务端报警才能知道接口出了问题,这个通过 UI 自动化也可以无人值守的监控:每隔一定时间跑一遍核心接口相关的 UI 自动化,同时用一些 cv 工具对页面进行白屏检测,那么如果出现问题,就能及时报警

UI 自动化的挑战

UI 自动化是否合理,在每一个测试团队推行 UI 自动化的时候都会遇到这样的争议。团队 leader 会觉得,自动化收益不明显、反而更耗费人力,业务测试 peer 会觉得,这是给自己工作增负,而且落地的好也只不过是给他人做嫁衣。这些矛盾的关键点在于:UI 自动化能否真正给团队带来效益?

UI 自动化其实难度很大,有一张很经典的三角形示意图,最底层面积最大的是Unit Test,cost 最小,收益最大,最顶端面积最小的就是UI Test,cost 最大,收益最小。做 UI 自动化,不光要求对框架的原理、app 的代码都有所了解,还要求对产品和业务非常了解。不清楚自动化框架的原理,case 出了问题无法排查。UI 自动化本质上也算是一种白盒测试,不了解客户端的知识也很难下手,比如不清楚 iOS 的证书体系,就无法为 app 注入代码执行 case,不了解安卓 UI,就会不理解为什么 QTA 对 UI 层的抽象设计。假设这些都了解了,也需要很熟悉产品业务。例如哪些场景有 ab test,ab test 如何解决,如何尽量减少对线上数据的影响等。同时,如何让编写的 case 稳定性更好、维护性更好也很有学问,避免使用坐标点击、考虑不同分辨率设备的 UI 界面、将 case 提取出公共场景解耦等等...

这些是对开发者的要求,从对框架的要求来看,什么算是 “优秀的自动化框架” 呢?我认为主要有以下几点:

  • 稳定性:尽量不出现因为框架不稳定导致 case 失败的情况
  • 易维护性:将 case 提取出一步一步的路径节点进行解耦复用
  • 易扩展性:例如通过 sdk 或者注入得到一个统一格式的 ui tree,框架层进行元素查找,再调用对应 driver 进行操作,不管以后接入什么终端,只要提供 sdk 和 driver,框架层不需要作出任何修改
  • 易编写性:我个人看法是 “去 IDE 化”,有些框架会提供本地 IDE 给开发者编写 case,但是环境的包袱太重,可以采用云 IDE,在云端利用云真机编写/录制生成 case,也不需要开发者在本地配置各种冗杂的环境,同时利用 mapping 文件云端解混淆,也可以做到对混淆无感知
  • 可分布式执行、并发执行:可以将 case 打到设备集群上并发执行,减少测试时长,也能增大机型/系统覆盖率

UI 自动化 2.0

从百度一路走来,在 UI 自动化方面踩了很多坑,刚写 case 的时候,没有注意 case 的解耦、复用,导致维护起来非常消耗人力,于是后来进字节之后,将 case 提取出公共场景进行复用,比如评论和买车都需要登录,就把登录场景单独拎出来给评论 case、买车 case 复用,这样如果以后登录 case 页面做出改动,也只要修改一个 case 就行。字节自研了一个自动化框架,叫 “Shoots”,但是编写这个 case 的上手门槛非常高,要求 QA 很熟悉 python 和客户端环境,虽然它提供了一个本地 IDE,但是 case 还是需要自己新建类自己写,非常不适合代码能力没那么高的业务同学用,于是师兄就带我开发了一个测试平台,设计了一套类似 uia2 的脚本语法,将生成的脚本用 jinjia 模版翻译成 Shoots 的代码,这样就曲线救国实现了 case 的自动生成。云真机的前端渲染是开发 app 的 SDK 提供截图 +ui 树(Native 控件使用原生代码获取 ui 树,webview 界面通过向 webview 注入 js 获取 ui 树),发给服务端生成预览。

UI 自动化的 2.0,意味着要放宽思路,很多技术都可以应用于 UI 自动化中。例如通过 hook,对一些没有 id 的控件自动生成 id(https://github.com/yulingtianxia/TBUIAutoTest ),降低元素定位难度。例如将一些 cv 算法用于 UI 自动化测试过程中判断界面是否存在花屏/白屏,图像对比、模版匹配算法对比两幅图像是否一致,可以用于性能测试时获取开始帧、结束帧,也可以判断 ui 自动化测试的结果是否符合预期。还可以结合fuzz test,利用 UI 自动化访问特定接口进行接口健壮性测试。

客户端自动化的未来:AI Test

现在很多公司都在 AI Test 方面进行探索,客户端的话主要是自动测试生成(Automated Testing Generation)技术,编写 case 不再需要工程师,而是可以自动生成和维护 case,目前在稳定性测试方面落地得比较好(https://github.com/bytedance/Fastbot_Android )。case 生成主要有两种思路,一种是提取出界面的控件,对 Activity/ViewController 进行 bfs/dfs/A* 搜索,还有一种是利用线上用户的行为提取行为链进行 case 生成。

共收到 2 条回复 时间 点赞
1楼 已删除
2楼 已删除
6楼 已删除

目前来看,我觉得固定业务流程的自动化脚本 + 探索性自动化测试的模式更好一点,case 自动生成还是需要人维护

cool 回复

case 的自动生成我个人觉得会是一个趋势,目前已经有工具可以实现对 Activity/VC 进行自动遍历,覆盖到绝大多数的场景,现在只能抓取遍历过程中的 crash,但我相信随着发展,未来一定能在 case 运行过程中加入 UI 断言等校验。至于维护,如果 case 还需要人维护的话,那这个 case 不能算是 “自动生成” 的

兔子🐰 自动化测试合辑 中提及了此贴 02月21日 17:01
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册