写点什么

Flutter UI 自动化测试技术方案选型与探索

  • 2021-06-11
  • 本文字数:2693 字

    阅读完需:约 9 分钟

Flutter UI自动化测试技术方案选型与探索

Flutter 页面无法直接使用 Native 测试工具定位元素,给自动化测试带来很多不便。虽然 Google 官方推出了 Flutter driver 和 Integration test,但是在实际使用中存在以下问题:

  • 不适用于混合栈 APP,虽然 appium 中有相关的 driver,但是无法切换环境。

  • 元素定位能力相对薄弱。

  • 依赖于 VMService,需要构建 Profile 或 Debug 包。


基于以上因素,我们并没有直接使用 Google 官方推出的工具,而是选择基于 Native 测试工具去扩展 Flutter 页面的测试能力。本文对 Flutter driver 和 Integration test 的原理和实现进行了分析,同时简单介绍闲鱼在 UI 自动化测试的尝试方案。

Flutter driver

最早接触 flutter 自动化测试时,先尝试使用 appium 框架去驱动 APP,当我们使用 inspect 功能去 dump 页面元素时发现很多元素会被合并成一个区域块,然后点击的时候只能通过 xpath 定位,想定位到某些具体的元素会比较困难,并且 xpath 其实是容易改变的,代码可维护性能力差。


因为上述原因,我们开始调研 Flutter 官方提供的测试工具——flutter driver。一开始使用该框架的时候发现它只能适用于纯 Flutter 应用,对于混合栈应用并不适应,但是它底层提供的元素定位能力或许对我们有用,于是我们对它的源码进行了剖析,该框架的原理图 1 如下所示。

null

图 1 flutter driver 原理图 


整个框架的流程交互比较简单,测试脚本在运行时,首先利用 FlutterDriver.connect()来连接 VMService 获取相关的 isolate,之后通过 websocket 来传输操作过程以及数据获取。其中测试脚本侧的所有操作都是被序列化为 json 字符串通过 websocket 传递给 ioslate 来转换为命令在 APP 侧执行,例如我们想要获取某个组件的文本内容,其最终生成的 json 结构体如下:


{    "jsonrpc":"2.0",    "id":5,    "method":"ext.flutter.driver",    "params":{        "finderType":"ByValueKey",        "keyValueString":"counter",        "keyValueType":"String",        "command":"get_text",        "isolateId":"isolates/4374098363448227"    }}
复制代码


了解上述原理后,就可以通过构造协议格式,在任何语言、测试框架下都能够去驱动 flutter 测试,所以我们对这个协议进行了封装,使用 Python 进行驱动,这样可以在使用 uiautomator2 和 facebook-wda 的基础上来测试 flutter 页面,以满足 flutter 混合栈应用的测试需求。最终的实现代码 demo 如下。


from flutter_driver.finder import FlutterFinderfrom flutter_driver.flutter_driver import FlutterDriverimport uiautomator2 as u2
if __name__ == "__main__": d = u2.connect() driver = FlutterDriver(d) if pageFlutter is True: # 如果是flutter,则使用flutter driver进行驱动 driver.connect("com.it592.flutter_app") finder = FlutterFinder.by_value_key("input") driver.tap(finder) time.sleep(1) print(driver.getText(FlutterFinder.by_value_key("counter"))) else: d(text="increase").click()
复制代码


我们尝试使用该套框架,发现其实 flutter driver 底层提供的能力相对比较薄弱,并不能完全满足我们的需求,主要问题如下:

  • 不能批量操作元素,一旦 finder 定位到的元素超过 1 个时,就会抛出异常。

  • 很多时候开发同学不写 key,元素定位也没那么方便。

  • 因为 flutter 没有 inspect 工具 dump 元素,所以只能利用结合源码去写脚本,代码维护成本比较高。

  • 官方已经放弃维护该项目,所以后续估计也不会有新功能支持。

integration_test

前面提到,flutter 官方放弃维护 Flutter driver,并推出新的测试框架 integration_test,那么这个框架会不会对混合栈应用予以支持呢,事实上试用了之后发现事情并没有我们想的那么美妙。在官方文档里有这么一句话“该软件包可在设备和模拟器上对 Flutter 代码进行自驱动测试”。


integration_test 底层的元素操作和定位还是基于 flutter_test 去驱动的,其优势主要如下:

  • 测试脚本可以使用各种 Flutter 的 API。

  • 打包 ipa、apk 后就能在 Firebase Test Lab 等设备群上运行测试,不需要额外驱动。

  • integration_test 的每个页面之间测试无关联,可以实现单个页面级别的测试。


但是由于底层元素定位和 Flutter driver 的是一致的,所以 Flutter driver 存在的问题依旧存在,同时还存在其他局限问题:

  • 测试脚本打包到 APP 中,每次修改脚本都需要重新打包。

  • 对端到端测试不够友好,需要额外函数来等待数据加载完毕。

  • 不适合全链路级别的页面测试。

  • 可扩展性弱


基于以上问题,不满足我们的使用需求,所以我们只是做了简单预研,并没有深入了解和应用。

闲鱼 UI 自动化测试方案

学习 Flutter 官方推出的相关测试框架之后,我们开始思考闲鱼 UI 自动化到底要怎么走?是站在官方的肩膀上去造轮子还是复用现有的原生自动化测试能力去扩展 Flutter 测试能力。在综合考虑投入成本以及测试脚本的维护难度后,我们选择使用图像处理技术来扩充原生自动化框架对 Flutter 页面的测试能力支持,整个测试方案架构如图 2 所示。

null

图 2 闲鱼 UI 自动化测试方案架构

 

Flutter 的元素不是完全不能被 uiautomator2 和 facebook-wda 识别,所以编写测试脚本时只需要处理不能被识别的元素即可。对于有 name、label 以及 xpath 不易改变的元素定位,我们优先使用原生定位能力进行定位操作,其他元素则直接使用图像处理技术进行定位操作。


在处理无法使用原生能力定位的元素时,我们优先使用 ocr 文字匹配来进行定位,准确率较高,不容易受分辨率的影响,对于纯图片则通过图片查找的方式进行定位。对于一些常见的元素控件例如商品卡片、价格、icon、头像等,我们构建一个训练集,使用图像分类来判断元素的类型,从而实现常用控件的定位。

UI 自动化面临最大的问题就是——随着版本的迭代,测试脚本也需要进行不断迭代。所以在方案选型和脚本编写过程中需要考虑到脚本的健壮性以及可维护性。我们在实际脚本开发中将页面元素封装到单独的类中,并与测试逻辑分离,从而保证后期元素迭代时只需要修改对应的页面元素即可,减少维护成本。


null

图 3 脚本分层结构 


闲鱼性能自动化测试的相关 UI 操作已经使用该方案,在脚本编写时,并不需要区分当前页面是什么类型。我们的脚本已经稳定运行 500+次,成功率超过 98%。

总结

null

图 4 方案对比 


从图 4 可以看出,无论是 flutter driver 还是 integration test 对混合栈的支持不够成熟,但是 flutter driver 可以进行一些扩展,对于纯 Flutter 应用而言,采用该方案能够基本满足测试需求,而 integration test 相对没有那么成熟,对于混合栈应用的测试,可能还是需要考虑混合栈的场景切换成本,使用一些 ocr 技术去做一些扩充可能成本更低,收益更大。


本文转载自:闲鱼技术(ID:XYtech_Alibaba)

原文链接:Flutter UI自动化测试技术方案选型与探索

2021-06-11 13:004242

评论

发布
暂无评论
发现更多内容

TDengine3.0计算查询引擎的优化与升级

TDengine

数据库 tdengine 时序数据库 企业号九月金秋榜

精彩演讲实录|在确定性和不确定性中探索AIOps的适用性

TRaaS

技术文章

我们做了一个云原生成本优化产品

TRaaS

软件测试 | 测试开发 | AppCrawler 自动遍历测试实践(三):动手实操与常见问题汇总

测吧(北京)科技有限公司

测试

iOS 自动化测试踩坑(一): 技术方案、环境配置与落地实践

霍格沃兹测试开发学社

iOS自动化真机测试验证环境过程中常见问题解析

霍格沃兹测试开发学社

新书上市 | 十分易上手的图解教程,全系列累计销量20万册!

图灵社区

程序员 计算机 图论

开源治理的基本实践与指导原则

SEAL安全

开源 开源安全 软件供应链安全 开源安全与治理

为什么资源隔离对HTAP至关重要?

OceanBase 数据库

开学季 | Y 省教育厅这张卷,融云答出了100分!

融云 RongCloud

通讯协议

《穿越时空的git》之创建版本库和常用命令操作

霍格沃兹测试开发学社

最新版!955、不加班、双休的公司名单

千锋IT教育

软件测试 | 测试开发 | 一文搞定 uiautomator2 自动化测试工具使用

测吧(北京)科技有限公司

自动化测试

【译】YouTube 架构

Rae

数据库 架构 youtube 后端技术

TiFlash 源码解读(七)TiFlash Proxy 模块

PingCAP

TiDB TiDB 源码解读

fastposter v2.9.2 最简海报生成器

物有本末

海报生成器 电商海报 图片生成

易观分析&Pangle联合发布《全球新兴市场移动应用报告》

易观分析

新兴市场

软件测试 | 测试开发 | 常见接口协议解析

测吧(北京)科技有限公司

TCP

hive on spark 还是 spark on hive?

一生要强的查数姑

大数据 hive spark SQL 大数据仓库

内核实战教程第四期 _ 带你走进数据库 SQL 引擎

OceanBase 数据库

软件测试 | 测试开发 | 如何使用代理配置快速定位接口测试脚本问题?

测吧(北京)科技有限公司

测试

RPC接口测试技术-Tcp 协议的接口测试

霍格沃兹测试开发学社

【译】日志:每个软件工程师都应该了解实时数据的统一抽象【一】

Rae

架构 分布式 日志 原理

TiDB v6.2 发版

PingCAP

#TiDB

Python代码用在这些地方,其实1行就够了

华为云开发者联盟

Python 开发 企业号九月金秋榜

小程序可以在智能设备上运行?

Speedoooo

小程序 物联网 IoT 智能设备 小程序容器

新书上市 | 十分易上手的图解教程,全系列累计销量20万册!

图灵教育

程序员 计算机 图论

软件测试 | 测试开发 | 测试人员必须掌握的测试用例

测吧(北京)科技有限公司

测试

不信谣不传谣,亲自动手验证ModelBox推理是否真的“高性能”

华为云开发者联盟

人工智能 企业号九月金秋榜

宏杉科技加入阿里云PolarDB开源数据库社区

阿里云数据库开源

阿里云 polarDB 阿里云数据库 PolarDB-PG PolarDB for PostgreSQL

一文带你了解K8S 容器编排(上)

霍格沃兹测试开发学社

Flutter UI自动化测试技术方案选型与探索_架构_闲鱼技术_InfoQ精选文章