转转QA 转转 App UI 自动化进化史

笑哼 for 转转QA · 2018年06月27日 · 最后由 志阳、 回复于 2018年09月05日 · 4800 次阅读

原创: 张志阳 转转 QA

一、 概述

背景

每个版本都需要执行大量的老功能回归 Case,重复工作量较大

随着 App 功能的逐渐增加、回归测试点逐渐增多,在保证测试覆盖度的前提下,整体的回归测试时长在增长,增加了测试压力

在针对老功能回归测试的过程中,因回归测试点比较多,可能存在测试点漏测的情况

目标

覆盖大部分的回归测试 Case,帮助大家执行部分功能的回归测试,减少回归测试的人工成本

利用 UI 自动化测试 自由分配、随时可执行的优势,增加已有功能的测试频率,在版本开发工程中,尽早发现因新更改影响已有功能的情况

不局限于已有功能的验证,利用 UI Case 的操作场景,在执行过程中进行其他数据的收集,供其他测试类型使用

对线上已发布的版本,进行主流程功能监控

二、 框架介绍

1、UI 自动化框架

UI 自动化测试框架有很多,基于以下几点考虑,选择使用 Appium 框架

转转 Android & iOS 的 App 功能交互&设计始终保持一致,使用 Appium 可以保证一套操作逻辑,两端都可以使用,减少 Case 创建&维护成本

Appium 支持 Native 、Webview 、混合页面的测试

属于外部测试框架、结合支持多种语言的优点,更方便扩展使用

2、UITest 框架结构

框架是 UI 的基础,框架的稳定及易用,决定了 UI 自动化的整体流程的效率及稳定

3、业务 Case

结构

参考 PageObject 设计模式,将 Case 的结构进行拆分管理,解耦的同时,更便于维护

case 存放位置

app 业务

属于基础业务,存放在 UITest 框架内部,可供其他业务使用部分已封装好的操作场景

其他业务

为了支持多业务使用框架,避免共同在单一工程中维护代码时互相影响,对框架进行了扩展支持

每个业务可以单独新建独立的工程进行 Case 的编写及维护。只需将 UITest 框架放置在工程内,将保存测试集的 suite 文件通过传参 或 在 suite 文件中调用 UITest 执行接口,就可以触发执行

4、测试结果

本地存储

存储位置:每次执行都会在工程-report 目录中创建独立的文件夹存储测试结果

存储内容:设备执行 Log(框架执行过程中的 log,非设备本身的 log)、失败 Case 截图、便于汇总查看的报告文件(html)

线上存储

每次的执行结果都会上报结果平台,存到数据库中,便于查看历史记录及详细的执行数据

三、 UI 自动化进化过程

1、控件定位方式

iOS Native 控件定位方式

初期:主要以 XPATH 为主 + Text 的方式定位控件,XPATH 定位较慢,App 布局改变后需要重新维护

RD 帮助补充 控件 NAME 属性后:将主要使用 XPATH 的方式定位,更改为主要使用 NAME & Text 的方式,降低了控件定位耗时,降低了 Case 执行耗时

图像识别 方式扩展

初期:iOS 和 Android 存在大量的共用图片、每个控件基本只有一张图片,在不同分辨率的设备上得到的相似度不同,会影响匹配结果判断

为每个平台创建单独目录保存图片:避免相同控件在不同平台上,图像略有不同,不能使用同一张图片识别

同控件根据不同分辨率,分别截图取样:定位控件时,先计算设备分辨率,优先查找同分辨率的图片样本进行识别

通过图片名称查找图片样本:没有通过分辨率查找到对应图片样本后,根据图片名称查找通用图片

支持 Webview 控件

初期:只执行了 Native 控件的识别及操作

现在:增加多种 Webview 定位方式的支持,从而增加了对 M 页功能的较好支持

2、控件操作方法

验证控件是否存在

图像识别

初期:只根据 Element 中存储的完整图片名称,查找图片

现在:Element 中存储的为图片名称关键字,根据平台查找平台目录,优先根据分辨率 + 名称查找图片样本,未找到再根据图片名称查找

iOS 控件增加实际显示位置判断

初期:通过 Text/Name 定位的控件,与 page_source 对比,根据 enable & visible 的值,判断是否可用,其他定位方式通过 Driver.find,查找到就认为可用。实际上 Appium 执行时获取 iOS 的 page_source 并不稳定,发现同一页面,有时可以获取到 iOS 中 当前页面已加载出的所有控件(包含为显示在屏幕区域内的),并不能进行有效操作,并且有些被 Tab Bar 由于被遮挡而不能正常操作到

现在:增加控件位置的计算、判断是否在屏幕可操作的区域内,若不在有效区域内,虽然可定位到,但因不可操作,也认为其不存在,配合滑动操作,将控件滑动到有效区域再操作

点击方法扩展

初期:只支持 Native 控件的点击操作

扩展支持 WebElement 类型

添加专项数据收集支持

滑动方法优化

根据设备屏幕分辨率,计算准确的坐标值,进行滑动

解决 iOS 滑动不好控制的问题,较好的控制滑动幅度

3、执行策略

触发方式扩展

初期:执行参数较少,基本只在配合 CI 时使用,本地多数还是直接运行 UiTest.py 触发执行的方式

扩展更多的执行参数,更自由、方便的控制执行配置,也可以较好的为外部的其他脚本/平台提供支持

封装执行接口函数,供外部工程调用框架执行时使用,参数与命令行参数一致,

多平台同时执行

解决多平台依次执行,整体时间过长,效率比较低的问题

Android / IOS 使用不同的预设起始端口启动 Appium,互相不冲突

使用多进程的方式,每个平台启动一个单独的进程用来启动 Case 执行

利用执行参数 –o 或者 修改 config 中的 optionsystem,控制当次执行时使用的平台

多平台多设备同时执行相同 Case

在进行功能测试的同时进行兼容性测试

在每个平台进程内,根据设备列表,为每个设备分配 Appium 端口,互不冲突

为每个设备再启动一个进程,独立执行 Case

每个设备单独统计测试结果、保存、发送报告

利用 –d 参数可以控制使用的设备

多平台多设备分配 Case 执行

Case 量越来越多,单设备全量 Case 的执行时长越来越长,多设备分配 Case 执行,可以提高执行效率、缩短整体耗时

根据 Case 列表筛选出每台设备都需要执行的初始化 Case 及 需要分配的 Case 集,结合设备列表,分配 Case 集,为每一个设备创建独立的 testsuite 文件

为每个设备分配一个进程,执行对应的 testsuite

当同平台的所有设备都执行完后,以平台为维度,进行结果汇总,保存结果、发送报告

利用 –g 参数可以控制是否分配 Case 执行

4、整个框架执行逻辑对比

初期:

现在:

5、UICase 筛选依据

UI 自动化 Case 并不能保证 100% 的覆盖所有的功能 Case,在不同的阶段的 Case 筛选依据会有所不同

建设初期(欠债)阶段:以回归测试的 CheckList 为依据,根据功能模块的重要性,设定优先级,逐步添加 Case

参与版本周期(进度持平)阶段:新功能 Case 的添加,优先以冒烟测试用例为依据,筛选出 UI Case 覆盖范围,再添加额外的 Case

四、未来

在 Case 可覆盖功能 、执行策略等方面,现有的 UITest 框架均已满足了基本需求,可稳定使用,后续的工作都为扩展,目的是增强 UI 自动化的作用,利用 UI 自动化做更多的事情

利用 UI Case ,获取更多的数据,驱动更多种类型的测试

可视化查看、操作、控制 UI 自动化 及相关测试的进行

持续集成、与 CI 结合、更自由、敏捷的执行

原文链接:https://mp.weixin.qq.com/s/MmoVNyocTuE7pdxZfhQBNQ

共收到 12 条回复 时间 点赞

学习了,能说一下设备管理这部分具体是怎么设计的吗?

隐身 回复

STF

看了楼主的思路,感觉还是非常不错的,给贵厂点个赞
有几个问题:
1、能说贵厂数据管理的思路是啥样的?
2、android 版本运行起来如果 ui2 有没有出现不稳定的情况,如果和我一样出现了,可否提供解决思路呢?
提供一点建议:
分布式执行去全量 case 时间还是一样久,可以试着全量 case 随机分配到机器分布式执行,最后结果统一,这样 case 跑起来会快的多

文贤平 回复

针对第一点:Ui 自动化 case 里的数据是在 Ui test 工程中,另外失败截图、log 日志、历史数据等都是在自动化平台上;
针对第二点:不知道你说的不稳定的具体错误,我这边目前没问题,当然刚开始使用时会出现一些问题,不过已经解决了;
另外针对你的建议:
其实是我们这边做的其中之一,我这边分布执行全量 case 有开关控制,开关打开,假设全量 case 为 n,设备为 m,那么每个设备的 case 数量就是 n/m;如果开关关闭,那么每个设备的 case 数量就是 n

想请教下,你们有没有做失败重测这块的工作,如果做了 是怎么做的 给点思路

是说运行失败的 ui case 重新运行么?(失败的 case 单独记录下来重新再跑一遍)还是说运行失败的 ui case 怎么处理?(首先确认下是否是 bug 呗,不是 bug 的话就是代码的问题)

隐身 回复

现在:
设备管理方面:我们在做一个设备管理平台,已经上线试用,主要是分布式管理,在多台设备上安装 Agent 服务,实时与设备平台同步信息, 设备平台也会下发任务给 Agent 服务,指定设备执行特定的任务
设备控制方面:Android 如笑哼所说 暂时接入 STF,iOS 还在调研,可能先试用一些各位大佬已开源分享的方案

以前:
UI 框架: 执行时,会 获取已连接设备列表,获取当时 预使用的 Appium 端口占用情况 ,根据执行时设备的选择(配置的设备平台 和 是否指定了设备),为设备分配端口执行
测试平台未接 设备平台时,本地服务异步更新设备连接状态,设备有 是否被占用 & 是否连接 两种状态,用来区分设备是被测试占用,还是未在线不可用,哪些是已连接并且可用的。端口处理同框架。设备基础信息的存储

wtnhz 回复

Ui 框架本身,可以设置失败重试次数,当 Case 执行失败时,会立刻进行重新执行,结果会分开保存。
测试平台,因为框架本身有重试测试次数设置,所以也可以配置重试次数,下发任务执行
测试平台本身,也提供了批量重新执行的策略,在一次测试记录的测试结果页面 或者 测试计划配置页面, 可以一键触发 重新执行,上次执行记录中的所有失败 Case,重新执行前,可以更改分配的设备 和 使用的被测应用安装包

文贤平 回复

数据管理:
Case 所需测试数据,有专门的文件存储测试数据,有特定的方法提取测试数据,所以编写 Case 的时候,补充好就可以了。
Case 执行所需的前提条件数据:会有方法进行数据创造,之后再执行测试逻辑
Case 执行过程数据:Case 执行过程中,会产生 框架 log ,Case 执行 log,Device log, 失败时截图,及 Case 视频,log 及截图,本地会保存文件,也会在执行结束后通过平台接口,上报给平台存储,方便通过平台查看 Case 执行过程,Case 视频会直接上报平台 ,不会本地存储,文件的存储会使用 ftp, 测试结果及执行信息 会存储数据库
Case 执行产生的应用数据: 会在测试结束后,通过特定的方式,将产生的测试数据进行清理

Case 分量执行建议:
如笑哼所说,框架本身有配置开关控制,是否在使用多设备时,进行 Case 分量执行,各执行一部分,设备越多,使用的时长会越短
测试平台方面:有一个后续的计划,一直都保留着 Case 在 各个设备 及版本上 成功 / 失败的执行耗时, 可以利用这个数据,在选择 Case 列表 和设备后, 根据历史数据,进行计算,计算出,预计最短时长的分配方案,尽量保证各个设备使用的时长相近。

志阳、 回复

我这两天也在搞 iOS 方面的支持。欢迎交流。

隐身 回复

带上我

隐身 回复

好啊好啊😀

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册