贝壳 Flutter UI 自动化测试原理与实践 - 已开源
开源地址
贝壳 Flutter UI 自动化测试库开源地址:https://github.com/LianjiaTech/flutter_ui_auto_test
一、引言
Flutter 是 Google 推出的跨平台 UI 框架,一套代码,多端复用,性能上可媲美原生。Flutter 的诞生,引起业界的广泛关注,越来越多的互联网公司在 APP 中使用 Flutter 技术,像 BAT、TMD 等国内互联网公司,研究和使用都比较深入。Flutter 技术的引入,研发原来需要为 Android、iOS 编写两套代码,现在仅需编写一套,移动端研发的效率得到了大大的提升。但对于移动端测试同学而言,仍需对不同的平台做测试,工作量并没有同等比例减少。由于原有 Native 的自动化框架识别不到 Flutter 页面元素, Flutter 页面也就不能通过自动化的方式进行回归测试。 随着 Flutter 页面的增多,可通过自动化手段测试的占比随之降低, QA 人工测试的成本越来越高。那么我们如何提高 Flutter 页面的回归测试效率就迫在眉睫,于是我们开启了 Flutter UI 自动化方向的探索与研究。
二、方案调研
通过调研,目前业界自动化框架对 Flutter 的支持并不完善,不能满足我们的业务述求。基于此,我们从稳定性、业务接入成本以及兼容性等方面进行调研,对比结果如下:
代码侵入性:方案本身是否需要对业务代码进行改动
脚本语言:编写测试 case 的语言(针对 QA, Python 语言为最佳)
key 值:可以标示唯一页面元素的值
KeMTC:贝壳现有的移动端测试平台,目前各个业务团队已稳定接入。
Flutter-driver : Flutter 官方提供的集成测试方案,有着丰富的 API,但需要在业务代码中手动设置视图的 ID,对业务代码有侵入;另外,只支持 Dart 语言编写测试脚本,不支持 Python,无法集成到 KeMTC 项目中,对于移动端测试同学增加太大的学习成本。
Appium-flutter-driver :是对 Flutter-driver 的封装优化。Appium 是一种跨平台 UI 自动化测试框架,借助 Appium 的能力,可以用 Python 编写测试脚本;但是 Appium-Flutter-driver 并没有解决 Flutter-driver 的需要手动设置视图 ID 的痛点。
经过详细的调研对比:以上两种方案都无法满足业务的需求,尤其是在稳定性、接入成本方面。于是我们开启了 Flutter UI 自动化 Ke-FUT( Ke-FlutterUiTest 的简称)的自研之路。
三、技术原理与实现
3.1、概述
Ke-FUT 自动化的整体设计思路与原生相似,如图所示共有两个主要的步骤:
获取元素 ID: ID 是指可以标示唯一页面元素的值。自动化测试脚本通过这个值去映射到对应的页面元素进行操作。
驱动视图元素:针对对应的视图完成模拟操作,其中包括点击、滑动、长按、输入等。
贝壳内部使用 UIAutomator2(简称 U2)框架实现 Android 原生的自动化测试。在 U2 中“分析页面元素”和“驱动视图”借助 Android SDK 中的 UIAutomator 进行的。以此类比, Flutter 实现自动化测试也需要提供类似的能力。
3.2、项目架构
架构设计如图所示,共分为 3 层。应用层、桥接层和服务层。
应用层:提供了面向测试人员的使用接口,可以低成本接入到现有的自动化测试框架中。
桥接层:接受应用层的消息,调用服务层提供的服务。
服务层:运行在 Flutter App 中,向上提供分析页面元素,驱动视图等能力。
3.3、获取 ID 的原理及实现
Ke-FUT 获取元素 ID 是借助了 Flutter VM Service 的能力,对关键方法进行修改,以达到获取元素 ID 的目的。
VMService 和 InspectorService 是 Flutter SDK 提供的服务,其主要作用是帮助开发人员检查页面结构,从而在视图布局出现问题时快速定位原因。利用其稳定的页面结构分析和元素定位的能力,我们可以轻松的获取到元素 ID。VMService 在 Flutter 初始化时开启,我们可以通过脚本启动 InspectorService 去连接 VMService,成功连接 VMService 之后,发送“show”消息使得 Flutter 页面进入 SelectedMode 模式,当前页面元素即可被选中,具体代码如下:
在 SelectedMode 模式下,点击元素会触发 VMService 的 WidgetInspectorService 类中的_getSelectedWidget 函数,该函数将 Element 的调试信息返回给 InspectorService。我们使用 Beike_Aspectd(贝壳 Flutter Aop 开源框架)hook 此函数,在其返回的 Json 数据中增加了 ID 字段(具体实现原理在 3.4 小节详述),从而实现 Element ID 的监听,具体代码如下:
在 InspectorService 获取到 Element ID 之后,“页面元素分析器”只需要通过 WebSocket 和 InspectorService 建立连接就能将 Element ID 展示出来,从而实现了分析页面元素并获取对应元素 ID 的过程。
3.4、ID_generator 的原理及实现
ID_generator 的作用是将 Flutter 中的页面元素 Element 映射成 ID 。在上一步中获取的 ID 值就是 ID_generator 映射成的,具体的过程如图:
查找 Element 路径:通过当前 Element 调用 visitAncestorElement 函数递归访问父 Element 获取的 Element 集合。
生成 Widget List: 记录 element 路径中的分岔点及分叉方向和首尾元素。记录尾元素在最后分叉中在多个同样类型的位置。
生成 Element ID:这步比较简单,使用/对 Widget List 做分割即可。
具体代码如下:
3.5、驱动视图的原理及实现
在获取 Element ID 之后,我们的测试脚本可以使用 Element ID 通过 Ke-FUT 驱动对应的视图元素。而驱动视图的过程实际上就是 FUTClient 和 FUTService 通信的过程。
3.5.1、FUTService
FUTService 运行在 Flutter App 上,通过 WebSocket 连接 FUTService 可以对 Element 进行信息获取、断言和输入等操作,具体过程如下图:
目前支持如下 API:
getPositionById:通过 Element_Id 获取元素相对于屏幕左上角的绝对坐标
getPositionByText:通过文案获取元素相对于屏幕左上角的绝对坐标
setText:通过 Element_Id 找到对应的 TextField 并设置输入值
assertText:检测 Element_Id 对应的元素是否展示对应的文案
clickById:通过 Element_Id 点击元素......
3.5.2、FUTClient
FUTClient 通过 WebSocket 调用 FUTService 的服务, 完成驱动视图并向上提供可供测试人员编写自动化脚本的 API。
现有的自动化测试框架可以通过实现 FUTClient 完成 Flutter App 的 UI 自动化测试。目前我们使用 Python 语言实现了 FUTClient,并将其集成到贝壳内部的 KeMTC 平台中,接入过程简便,成本低。FUTClient 实现提供如下 API:
click_id:通过 Element_Id 获取元素进行点击
click_text:点击页面的唯一 Text
set_text:在指定 ID 处输入 Text
find_element_by_text:根据 Text 进行查找
find_element_by_id:根据 Element_Id 进行查找
swip_down_element:下滑到指定位置
assert_exited_text:断言 Text 是否存在
assert_exited_id:断言 Element_Id 是否存在
assert_equal:断言 Element_Id 的文案与实际文案是否一致......
四、Ke-FUT 实践
4.1、获取元素
在 Flutter 工程根目录下,执行 flutter attach,进入 App,复制链接。
利用 flutter_devtools 工程 ,执行 dart auto_test_main.dart “复制的连接”。
打开 bk_weditor,点击 Connect Flutter,点击 show,操作界面即可看到 flutterId(如图)
4.2、编写用例
以贝壳租赁的调价功能为例,用例脚本如下:
效果如下:
五、Ke-FUT 未来展望
目前 Ke-FUT 项目已经在贝壳租赁业务上接入,从使用上看, Ke-FUT 已经支持常见的自动化操作并且运行良好,但是整体上仍然处于起步阶段,这也是我们对 Flutter UI 自动化测试的初步尝试。后续我们将在继续对方案进行迭代,提高稳定性,优化 FUTClient 和 FUTService 通信时的异常处理逻辑,提高用例执行时的稳定性。
版权声明: 本文为 InfoQ 作者【贝壳大前端技术团队】的原创文章。
原文链接:【http://xie.infoq.cn/article/bef0313ec421079ebe718de90】。文章转载请联系作者。
评论