干货 | Trip.com 智能自动化探索测试

2023-10-25 09:20

本文主要是介绍干货 | Trip.com 智能自动化探索测试,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者简介

 

祥星,携程Android开发工程师,对Android自动化测试有深入的研究。

一、简介

快速的业务迭代要求快速的App发版节奏,随之而来的是质量保障压力的增大。而增大自动化程度,提升QA效率就是一种非常重要的手段,以适应快速发版的要求。

自动化探索是一种模拟用户行为,不停地在页面上点击、滑动、输入,以期望进入更多页面的一种软件测试方法。这种方法的核心在于能自动化地覆盖到常规case之外的路径,发现预期之外的问题,是众多QA手段中的一环。大家比较熟悉的Monkey是最典型的自动化探索工具,它像猴子一样在屏幕上快速地点击。Monkey的测试思路非常简单:每次从当前页面随机选择一个点(x,y)触发,这一过程一直持续直到结束。

一种典型的应用场景就是通过自动化探索跑到一些corner cases,提前发现App Crash,以降低Crash率。这种场景下对于自动化探索的核心要求就在于所能触达的页面,更进一步地是所能覆盖的软件执行路径。但 Monkey 的问题在于,屏幕上大部分区域都不可点击,其触发的大部分事件都无效,又因为是纯随机触发,事件存在大量冗余。这就导致Monkey的探索效率不高。

因此,我们提出IAET(Intelligence Android Exploration Tool)的智能自动化探索工具,一个能有效检测当前页面元素,智能化展开探索的自动化工具,以尽可能触达更多页面和软件执行路径。

本文主要内容包括:第二章UI驱动,介绍有效元素检测;第三、四章介绍探索算法及优化后的探索算法;第五章介绍工具实现;第六章介绍探索成果;第七章介绍对比实验;第八章总结。


二、UI驱动


2.1 UiAutomator简介

Uiautomator是谷歌推出的UI自动化测试框架,用于模拟点击每个控件元素,并确认输出的结果是否符合预期。UIAUtomator除了根据resource-id、content-desc、text来查找元素之外,还提供了获取页面上所有可点击元素的能力。


2.2 利用UIAutomator查找所有可点击元素

UiAutomator提供的 UiAutomation#getRootInActiveWindow() API能够获取页面上所有元素,效果等同于uiautomatorviewer查看到的页面布局树上的属性。

下面举例如何通过AccessibilityNodeInfo获取当前页面所有点击元素:

// 递归获取当前节点所有可点击的子节点
public static void getCurrentAllClickViews(AccessibilityNodeInfo nodeInfo, List<AccessibilityNodeInfo> list) {if (nodeInfo == null)return;if (isVisible(nodeInfo)) {if (nodeInfo.isClickable() && notEditText(nodeInfo)) {list.add(nodeInfo);}if (nodeInfo.getChildCount() != 0) {for (int i = 0; i < nodeInfo.getChildCount(); i++) {getCurrentAllClickViews(nodeInfo.getChild(i), list);}}}
}

通过上面的方法就能获取一个页面所有可点击的元素。


2.3 运行

我们使用 app_process 运行UIAutomator[1][2]。首先编写一个可以连接UIAutomator的JAVA程序,然后再将JAVA程序push到手机设备中,最后使用app_process启动JAVA进程,与UIAutomator建立桥梁。

使用方式如下:

第一步,创建UIAutomaion桥接类。

public class UiTestAutomationBridge {public void connect() {...mUiAutomation = new UiAutomation(mHandlerThread.getLooper(), new UiAutomationConnection());mUiAutomation.connect();...mUiAutomation.setServiceInfo(info);}public AccessibilityNodeInfo getRootInActiveWindow() {return mUiAutomation.getRootInActiveWindow();}
}

第二步 创建一个Main函数调用connect方法,获取RootNode。

public static void main(String[] args) {UiTestAutomationBridge.getInstance().connect();AccessibilityNodeInfo rootNode = UiTestAutomationBridge.getInstance().getRootInActiveWindow();
}

第三步将JAVA文件打成jar包,使用app_process运行jar包。

adb shell CLASSPATH='/data/local/tmp/iAET.jar' '/system/bin/app_process' '/data/local/tmp/iAET.jar' com.testing.Main

具体如何使用app_process运行JAVA程序,见参考文献[2]


三、探索算法1.0


3.1 App模型图

在理想的模型中,一个无页面状态的App模型,可以刻画成一幅模型图,其中节点代表页面,边代表事件。

以Trip.com首页为例,首页点击机票、酒店和火车按钮分别跳转到机票首页、酒店首页和火车首页。机票、酒店和火车又有自的跳转页面,这一过程一直持续,直到页面无事件为止。

研究App的遍历问题本质上就转化成研究图的遍历问题,因此我们借鉴图的深度遍历算法制定探索策略。策略如下:

  • 页面事件随机触发,触发过的事件不再触发

  • 若跳转到新页面,则优先触发新页面探索

  • 新页面事件触发完毕返回上一个页面

  • 新页面事件未触发完毕返回上一个页面,则重新回到新页面。

第四条避免随机点到返回按钮的问题。

以下面模型图为例,我们介绍App的探索过程。

  • 以A节点作为初始节点,从A节点的事件集合随机选择{e1, e2, e3}一个事件e1

  • 进入B页面。遵循规则1,以B节点作为当前节点,随机从{e4, e5, e6}选择事件e4

  • 停留B页面。遵循规则2,去掉e4事件,随机从{e5, e6}选择事件e5

  • 返回A页面。遵循规则1,B页面优先于A页面触发,重新回到B。

  • 遵循规则2,选择触发最后的e6事件

  • 进入E页面。E页面触发事件e9

  • 进入F页面。遵循规则3,返回上一个E;遵循规则3,返回B;遵循规则3,返回A。

  • 至此页面B、E、F探索完毕。

流程简化为:

pb是 press back的缩写。


3.2 算法

算法的整体思想是采用递归的方式不断地在新状态下执行探索,直到探索完成。

算法说明:

  • 算法输入是App的首页MainActivity,执行时间runningMin和一个访问过的事件集合visitedEvent

  • 第1行:MainActivity 作为当前页面S

  • 第2~3行:运行时间大于执行时间结束运行。

  • 第4行:获取当前页面下所有有效的事件集合L

  • 第5行:有效事件集合L减去访问事件集合visitedEvents得到剩余待触发事件集合L

  • 第6行:若集合L为空,则跳转至第9行,否则执行第七行

  • 第7~8行:从L随机选择一个事件触发,并记录触发后的新页面记做newState

  • 第9行:根据新页面newState和旧页面S判断是否是返回事件,若是,则从上一个页面重新回到当前页面即第10行

  • 第11行:将事件event加入访问事件集合visitedEvents

  • 第14行:当前Activity页面作为当前页面S,重复3。


四、探索算法2.0

第三章提到的App模型是一种理想的模型,一种无状态的模型。事实上,App经常出现一个页面多种状态的问题。

4.1 App状态

在3.1节我们提到App的模型图是由页面和事件构成,节点代表页面,边代表事件。实际上,我们发现一个页面可能具有多种不同的状态。下面以Trip.com的机票搜索为例来举例。

Trip.com机票不同搜索结果

上图是Trip.com搜索不同目的机票的搜索结果。搜索热门城市香港到北京的机票,有数十趟航班,而搜索冷门城市马来西亚的BKI(亚庇国际机场)到巴哈马的ELH(北伊柳塞拉)的机票,却没有一趟航班。同一个搜索页面,搜索的输入不同,展示的结果不同。

App模型图无法表示具有状态的模型图,因此我们引入页面状态。

页面元素

引入页面状态之前,我们先定义页面元素。

页面元素是指页面上的一个个View组件,Android一般用resource-id 或者 content-desc表示。然而一个页面元素的resource-id可能相同(如列表),所以我们必须用一个能够唯一表示页面元素的方式。

我们想到了用xpath[3]来表示页面元素。

参考维基百科上xpath的定义:/A/B/C[1]/D[resource-id='value'] C节点必须是B的子节点(B/C),同时B节点必须是A的子节点(A/B),而A是这个XML文档的根节点。而D节点是C节点的第二个元素(C[1]),D节点的属性resource-id为value,[1]是称为节点的下标。

xpath是一种结合父元素、元素类型、元素id以及元素坐标的表示方法,能够精准定位一个元素。

酒店按钮的xpath是:

//FrameLayout[0]/FrameLayout[0]/FrameLayout[0]/TextView[@resouece-id="ctrip.english.debug:id/title"]
页面状态

页面状态是指页面所处的状态,我们用页面名称(Am)+所有页面元素(Xi)的集合来表示:

不同的搜索结果页,页面名称虽然相同,但页面元素完全不同。因此用页面状态可以区分不同的搜索场景。


页面事件

引入页面状态后,一个事件用三元组来表示E_i = <Am, Xi, An>,表示页面Am触发事件Xi进入An页面,其中Am称为源页面,An称为目标页面。


App状态模型图

引入App状态后,App模型图转变成App状态模型图。其中节点代表App的状态,边代表事件。

App状态模型图能够精准表示:在一个页面状态下触发某个事件,进入新的页面状态。

4.2 算法优化--相似元素

在介绍App状态模型图探索算法前,我们先小小优化第三章的算法。在第三章我们提出新页面事件触发完毕返回上一个页面

这一条值得讨论。

在第三章,我们页面事件触发完毕的条件是所有事件都触发一遍。事实上真的如此吗?

以相册页面为例,相册页面事件数非常多,但所有事件对应一个功能(勾选)。如果用第三章的算法,随机从n张照片选择一张,直到所有照片都选择一遍,将耗费很长的测试时间。

人工测试遇到这种情况,一般采用取样+相似的思想:随机选择几个事件,测试OK。其他事件与样本事件相似,测试通过。

同样地,我们工具也引入取样+相似事件的概念。

事件相似定义

元素相似

当两个元素X_i和X_j除了下标外,其他内容完全相同,称为相似元素,记做Xi≈Xj。元素相似潜在含义是布局树中相同层级的元素可能存在相似的行为。

状态相似

当两个页面状态Si和Sj 页面名称相同,页面元素都相似时,称为相似状态,记做Si≈Sj。状态相似的潜在含义是同一个页面状态相同,其行为可能相似。

事件相似

当两个事件Ei = <Sm, Xi, Sn> 和Ej = <S'm, Xj, S'n>,具有以下特征时:

  • Sm≈S'm

  • Xi≈Xj

  • Sn≈S'n

这两个事件相似。事件相似的潜在含义是这两个事件完全具有相同的行为。


相似事件处理

一开始页面的相似事件是空集,随着事件的发生,具有相同行为的事件不断增多。当相似事件集合超过阈值时,我们认为剩余的相似元素全部相似,相似事件不再触发。

相似元素的目的是减少功能相似事件的重复触发的时间,探索更多的功能。


4.3 App状态模型探索算法

虽然App模型由页面模型改成状态模型,但本质仍然是是图的遍历问题,所以只要稍作修改即可得出App状态模型探索算法。

执行同上,不再赘述。


五、工具实现


由IAET基础服务和探索驱动两大模块组成。

基础服务模块

基础服务模块在保证保证探索正常运行的基础上,承担UI驱动的能力,主要由UI驱动和异常监控系统两部分组成。

UI驱动模块主要提供UI的检测和驱动、区分事件类型、计算页面状态和计算相似事件等能力。

异常监控系统主要保证App探索期间发生crash的情况下能够继续运行。


探索驱动

探索驱动主要将探索算法应用于实践,并结合一系列自定义规则来对App进行定制化的探索。


自定义规则

实际探索我们往往遇到各式各样定制化的需求,例如输入用户名和密码、不能进入某些页面、只想探索某几个页面。探索算法无法满足这类要求的,只能靠自定义规则来完成。

这些规则包括:预输入模块、黑名单模块、模块探索等等。

下面以预输入模块为例:

iaet-preinput.json

{"data": [{"activity": "activityname","list": [{"contentDesc": "contentdesc","resourceId": "resourceid","text": "value"},{"contentDesc": "contentdesc","resourceId": "resourceid","text": "value"},]},]
}

预输入模块解决在哪个页面向哪些元素写入什么内容的问题,主要解决登陆注册、用户输入页面的问题。

如 iaet-preinput.json 文件所示,你可以在某个页面,向 contentDesc或者resourceid 为 XXX 的元素写入YYY值,解决那些因输入校验而阻碍探索问题。


六、探索成果

上图是Trip.com最近7个版本,IAET在发版前发现的Crash数和每次达到的页面数。CrashNumber列是发现的Crash数,ActivityNumber列是1h运行达到的页面数。

Q:为什么表格中7.5.0前后Activity Number发生两次跃迁?

7.5.0前没有相似策略,经常停留在长列表页面。7.5.0引入相似元素策略后,解决长列表问题,增加了其他页面探索的机会。

7.5.1前RN页面作为单个页面统计,7.5.1统计一个个RN具体页面的名称。

Q:如果增加探索时间,Activity Number还会增加吗?

目前测试的瓶颈在于订单页面。因为大部分没被探索的页面都是支付订单相关页面,线上包很难通过正常途径进入。除去支付订单页面,目前的页面覆盖率在80%以上。


七、对比实验

此外,我们还选择16个国内主流App作为实验对象,以APE[1]作对比工具,运行1h,以Activity覆盖率作为衡量标准展开对比实验。

实验分析

我们选择近年来学术界最新的开源、效果好的自动化测试工具APE作为对比工具。

实验的所有benchmark均是国内主流App,涵盖衣、食、住、行、教育、娱乐、新闻、运动、知识付费等各个类别,App下载量均超1亿。

最后两列是本次实验IAET和APE的实验结果,IAET在大部分App上所达到的Activity覆盖率比APE高,且有几个大幅高于APE,证明我们工具的优势。


八、总结

自动化探索提供的其实是一种基础服务能力,为性能测试、Crash检测或者页面内容检测等不同的测试目的提供测试基础。

此外,自动化探索还可以在弱网、无网和低内存等极端场景下的进行测试,以验证App的健壮性和稳定性。

参考文献

[1] T. Gu et al., "Practical GUI Testing of Android Applications Via Model Abstraction and Refinement," 2019 IEEE/ACM 41st International Conference on Software Engineering (ICSE), Montreal, QC, Canada, 2019, pp. 269-280.

[2]Android上app_process启动java进程, https://blog.csdn.net/u010651541/article/details/53163542

[3] xpath,https://zh.wikipedia.org/wiki/XPath

【推荐阅读】

  • 敏捷模式下携程的接口自动化平台演变

  • 高效率低成本,携程流量回放平台实践

  • 携程酒店DevOps测试实践

  • 《携程架构实践》《携程人工智能实践》上市啦!

《携程架构实践》

京东

当当

《携程人工智能实践》

京东

当当

 “携程技术”公众号

  分享,交流,成长

这篇关于干货 | Trip.com 智能自动化探索测试的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/281599

相关文章

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

智能交通(二)——Spinger特刊推荐

特刊征稿 01  期刊名称: Autonomous Intelligent Systems  特刊名称: Understanding the Policy Shift  with the Digital Twins in Smart  Transportation and Mobility 截止时间: 开放提交:2024年1月20日 提交截止日

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

基于 YOLOv5 的积水检测系统:打造高效智能的智慧城市应用

在城市发展中,积水问题日益严重,特别是在大雨过后,积水往往会影响交通甚至威胁人们的安全。通过现代计算机视觉技术,我们能够智能化地检测和识别积水区域,减少潜在危险。本文将介绍如何使用 YOLOv5 和 PyQt5 搭建一个积水检测系统,结合深度学习和直观的图形界面,为用户提供高效的解决方案。 源码地址: PyQt5+YoloV5 实现积水检测系统 预览: 项目背景