基于 Appium 的 Android UI 自动化测试!

自动化测试是研发人员进行质量保障的重要一环,良好的自动化测试机制能够让开发者及早发现编码中的逻辑缺陷,将风险前置。日常研发中,由于快速迭代的原因,我们经常需要在各个业务线上进行主流程回归测试,目前这种测试大部分由人工进行,费时费力,重复劳动多。如果能将UI自动化测试与主流程回归结合到一起,一方面保证了代码质量,另一方面大大节约人力成本,可谓一举两得。

为什么需要UI自动化测试

原因主要是以下三点:

  • 保证质量——及早发现代码缺陷,风险前置。

  • 减少重复劳动,节约人力——快速迭代中经常需要进行主流程回归,测试完整个主流程,需要耗费相当大的人力成本。

  • 统一标准——每个人对测试用例以及业务理解程度不同,标准可能存在不一致。

进行UI自动化测试面临的问题

  • 工具选择。

  • 降低对后端的依赖,避免因为测试环境后端不稳定导致的测试失败。

  • 整合测试用例,增加复用,降低用例维护成本。

自动化测试工具对比

业界UI测试工具发展迅速,目前有Robotium、Appium、Espresso、UIAutomator、Calabash等等,其中在Android中应用最广泛的当属UIAutomator、Robotium、Appium。

下面列表比较说明:

UIAutomatorRobotiumAppium
支持平台AndroidAndroid,H5Android,iOS,H5
脚本语言JavaJavaAlmost any
是否支持无源码测试YesYesYes
支持API级别16+AllAll

除了Android、Hybrid类型的App,Appium还可以在iOS设备上运行。加上之前组内有同事做过Appium方面的分享,在这方面有一定的基础,所以最终我们选择了Appium。

接口稳定性与数据可变性

业务特性决定我们的case在运行过程中会经常向后端请求数据,然后根据后端接口返回的数据决定页面元素展示。因此,有两个难点是必须克服的:

  1. 后端接口稳定性
    测试环境并不像线上,能在7x24内保持稳定。业务接口经常出现因所依赖的外部环境异常而请求失败的情况,以往处理这种情形,我们能做的事情往往很有限,最糟糕的就是必须要等待第三方修改完成后,才能继续我们的测试。因此,如何保持接口稳定,将成为UI自动化测试不得不面对的问题。

  2. 测试数据配置与保存
    克服了1中提到的接口稳定难点后,仍然要面对第二个难点——频繁修改配置以适应测试用例的条件。举个例子,对于闪惠业务,用例里面会对于商户配置的多种情况进行测试(无优惠、有优惠未开始、仅有闪惠优惠、有闪惠和团购、闪惠打折、闪惠赠品等),这里面的条件是复杂多变的。如果每一次进行测试前,都由执行测试人在商户后台登录后手动修改配置,将耗费巨大的人力成本。因此我们势必找出一条途径,将这种繁琐的配置过程自动化。

接入Appmock

注:使用Appmock,需建立在App底层网络请求模块已经具备切换mock地址的功能的基础上。

Appmock是美团点评平台组制作的非常优秀的mock工具,其前身是美团点评同事张文东所编写的wendong.dp(仅供美团点评内部使用)。在Appmock上可以进行网络请求的查看与mock。那么,是否可以让我们的自动化测试用例在运行时访问Appmock,获取预设的mock数据呢?做过相关App开发的同事都知道,在App中这是很容易实现的,只要访问某个特定HTTP链接进行注册即可。

现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:110685036

Appmock使用界面

图片

由此,“后端接口稳定性”的问题,在Appmock的帮助下就解决了,如果把后端数据直接配置在Appmock上,请求失败的概率就微乎其微。即便如此,仍然要面临频繁修改配置的需求,只不过是把修改的操作从商家后台页面转移到了mock系统。有没有什么方法,可以让修改配置的操作自动化进行呢?

在研读过Appmock的源码后,我们想到,可以自己搭建一个mock-server,把不同阶段的mock数据保存在数据库中,并且开放出网络接口,用来切换各个测试用例所需的mock数据。具体的系统结构如下图所示。

图片

上图描述了一次用例运行的简要过程,事前需要在数据库中准备好测试数据,mock-server基于Appmock,使用NodeJS进行二次开发完成。

编写测试用例

为了简化用例编写,减少开发与维护的工作量,使用Page Object模式进行用例开发。

Page Object定义为抽象页面的对象,通过对页面功能的封装,进行相应操作。它的优点是:

  • 减少重复代码,增加复用性。

  • 提高代码可读性、稳定性。

  • 易于维护。

图片

UI自动化测试框架的编写方式类似于MVC架构,我们将测试用例中的业务逻辑、各个页面间的元素以及测试数据相分离后独立编写,以下均用排队业务的主流程举例。

测试类组成

测试类的组成包括setUp(),tearDown()方法以及各个测试用例testXXXX(),所有的测试用例必须以小写test开头,如正常排号下的testQueueNormalQueue():

@Beforepublic void setUp() throws Exception {File apk = new File(APK_NOVA);DesiredCapabilities capabilities = DesiredCapabilities.android();capabilities.setCapability("device", Platform.ANDROID);capabilities.setCapability(CapabilityType.VERSION, "5.1");……       // capabilities各个常量字段driver = new AndroidDriver<AndroidElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);splashScreen = new SplashScreen(driver);mainPage = new MainPage(driver);……       // Page Object初始化}@Afterpublic void tearDown() throws Exception {driver.quit();
}@Testpublic void testQueueNormalQueue() {    // 略}

测试用例中不用直接对页面元素进行操作,我们所要做的事情仅仅是业务层面的逻辑,包括表单数据的提交、页面按钮的点击跳转等等。

页面类编写

页面类的编写采用Page Object模式,包括页面中会使用到的元素、页面元素的操作方法集以及页面元素的检验方法集。

所有的Page子类均继承BasePage父类,它要做的事情很简单,无非就是1个driver,2个driverWait用于延时加载的等待时间,以及页面元素的初始化:

public class BasePage {    private static final int TIMEOUT = 1;             // short timeout for web-elementprivate static final int TIMEOUT_LONG = 10;       // long timeout for web-elementpublic AndroidDriver<AndroidElement> driver;    public WebDriverWait driverWait;    public WebDriverWait driverLongWait;    public BasePage(AndroidDriver<AndroidElement> driver) {        this.driver = driver;        this.driverWait = new WebDriverWait(this.driver, TIMEOUT);        this.driverLongWait = new WebDriverWait(this.driver, TIMEOUT_LONG);PageFactory.initElements(this.driver, this);  // 这句非常重要,如果不写的话尽管编译不会报错,但是后面要说的页面元素在运行时一个都找不到}
}

然后是各个Page子类的实现方法:

public class ShopInfoPage extends BasePage {    public ShopInfoPage(AndroidDriver<AndroidElement> driver) {        super(driver);}…… // 页面元素 @FindBy…… // 操作方法,比如login()、clickXXXXXXButton()、gotoXXXXXXPage()…… // 检验方法,比如checkLoaded()、checkLoginSuccess()、checkQueue_LoginReadyQueue()}

Page子类的元素定位我们使用@FindBy注解方式进行统一的管理。

元素定位最基本的方法就是使用id/name/class等,如果不行的话就用相对复杂却无所不能的xpath,如:

// 点击登录按钮@FindBy(id = "login_tip")private WebElement clickLoginButton;// MAPI域名输入框@FindBy(xpath = "//*[contains(@resource-id, 'id/mapi_item')]//*[contains(@resource-id, 'id/debug_domain')]")private WebElement mapiDomainText;

Page中的操作和检验方法调用已经封装好的BaseUtils中的方法,如:

BaseUtils.waitForElement(driverWait, loginButton).click();                              // 等待元素出现并点击Assert.assertTrue(BaseUtils.waitForElementVisibility(driverLongWait, usernameText));    // 检验元素应该展示在页面上

BaseUtils方法

BaseUtils中封装好了一些通用的方法,还需要不断完善并扩展。下面介绍其中一些常用及重要的方法:

  1. openDebugPanel():每次直接调用该方法来打开Debug面板,由于Debug面板是一个系统层面的悬浮窗,它不属于任何页面中的元素(你完全没办法通过ID甚至XPath获得)。

  2. clickPoint():点击某个坐标+持续时间,坐标采用相对屏幕位移的方式(左上为0,0),这里只实现了简单的单指的点击操作,实际上driver.tap可以模拟多指的共同操作。

  3. swipeToUp() & swipeToDown():上拉 & 下拉页面操作,需要传的是次数和每次持续时间,模拟手指在屏幕上的滑屏操作,主要用于刷新页面以及绕过某些有坑的scrollTo。

  4. prepareMockData():这里要做的就是,在关键步骤操作前传入mock_data_id,我们会将数据请求发送给服务器,然后服务器从数据库拉到对应的mock data并更新。

  5. saveScreenshot():顾名思义,截图。在每个重要的页面操作方法中加入即可,需要传入的是case_id以及操作或检查时的keyword,方便在用例执行完以后看截图分析和Bug复现。

  6. waitForElementXXX():在预设等待时间内等待元素出现并定位元素。

UI自动化测试运行效果

在排队与闪惠两条业务线进行了UI自动化测试实践,它们执行完成全套用例的耗时均不超过20min。相比于之前人工进行主流程测试动辄花费半天的工作量的情况,大大降低了人力成本,将工程师宝贵的时间节约给了更有价值的研发工作。

当然,自动化测试前期的环境搭建、数据准备、用例编写等任务是必不可少的,这些准备工作很多都是一次性投入,一劳永逸,也正是自动化测试的价值所在。

今天的分享就到此结束了, 如果文章对你有帮助,记得点赞,收藏,加关注。会不定期分享一些干货哦....

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/122916.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring-底层架构核心概念

Spring底层核心组件 BeanDefinition BeanDefinition表示Bean定义&#xff0c;有很多属性用来描述Bean的特点&#xff1a; class&#xff0c;表示Bean类型 scope&#xff0c;表示Bean作用域&#xff0c;单例或原型等 lazyInit&#xff1a;表示Bean是否是懒加载 initMethod…

深度学习(4)---生成式对抗网络(GAN)

文章目录 一、原理讲述1.1 概念讲解1.2 生成模型和判别模型 二、训练过程2.1 训练原理2.2 损失函数 三、应用 一、原理讲述 1.1 概念讲解 1. 生成式对抗网络&#xff08;Generative Adversarial Network&#xff0c;GAN&#xff09;是一种深度学习模型&#xff0c;是近年来复杂…

私有云:【6】VCenter安装SqlServer

私有云&#xff1a;【6】VCenter安装SqlServer 1、VCenter安装SqlServer1.1、通过模板创建虚拟机1.2、安装sqlserver服务 2、搭建sqlserver群集2.1、安装群集功能2.2、在ad域服务器创建共享文件夹&#xff0c;供集群选举使用 3、创建故障转移群集【只需安装一台即可】3.1、创建…

地址解析协议ARP

地址解析协议&#xff08;Address Resolution Protocol&#xff0c;ARP&#xff09;&#xff0c;用于根据本网内目的主机或默认网关的IP地址获取其MAC地址。 ARP的基本思想&#xff1a;在每一台主机中设置专用内存区域&#xff0c;称为ARP高速缓存&#xff08;也称为ARP表&…

CTF-Crypto学习记录-第四天 “ “ --- SHA1安全散列算法,实现原理。

文章目录 前言SHA-1加密算法介绍关于SHA-1和MD5 SHA-1 加密过程原文处理设置初始值和数据结构定义加密运算原理过程 在python中调用SHA-1 前言 MD5学习MD5加密算法 SHA-1加密算法介绍 SHA-1&#xff08;Secure Hash Algorithm1&#xff0c;安全散列算法1&#xff09;是一种密…

深度学习:激活函数曲线总结

深度学习&#xff1a;激活函数曲线总结 在深度学习中有很多时候需要利用激活函数进行非线性处理&#xff0c;在搭建网路的时候也是非常重要的&#xff0c;为了更好的理解不同的激活函数的区别和差异&#xff0c;在这里做一个简单的总结&#xff0c;在pytorch中常用的激活函数的…

Table-GPT:让大语言模型理解表格数据

llm对文本指令非常有用&#xff0c;但是如果我们尝试向模型提供某种文本格式的表格数据和该表格上的问题&#xff0c;LLM更有可能产生不准确的响应。 在这篇文章中&#xff0c;我们将介绍微软发表的一篇研究论文&#xff0c;“Table-GPT: Table- tuning GPT for Diverse Table…

10.29数算小复习(选择题细节,二路归并,结构体排序)

排序、复杂度、细节&#xff08;选择题&#xff0c;判断题&#xff09; 对于一个已经排好序的序列&#xff0c;直接插入排序的复杂度是O(n)&#xff0c;而归并排序的复杂度是O(nlogn)。这时候归并排序就不比直接插入排序速度快了。 归并排序的最好、最坏、平均时间都是O(nlogn)…

STM32:TTL串口调试

一.TTL串口概要 TTL只需要两个线就可以完成两个设备之间的双向通信&#xff0c;一个发送电平的I/O称之为TX&#xff0c;与另一个设备的接收I/O口RX相互连接。两设备之间还需要连接地线(GND)&#xff0c;这样两设备就有相同的0V参考电势。 二.TTL串口调试 实现电脑通过STM32发送…

Kubernetes Label Selector

Author&#xff1a;rab 目录 前言一、Labels1.1 定义1.2 案例1.2.1 节点标签1.2.2 对象标签 二、Selector2.1 Node Selector2.2 Service Selector2.3 Deployment Selector2.4 StatefulSet Selector2.5 DaemonSet Selector2.6 HorizontalPodAutoscaler Selector2.7 NetworkPolic…

POJ 1201 Intervals 线段树

一、题目大意 给我们一些闭区间[ai , bi]&#xff0c;其中 1 < ai < bi < 50000&#xff0c;让我们求出一个集合&#xff0c;使得这个集合与 区间 [ai , bi]有 ci个共同元素&#xff0c;对于所有的 1<i <n个区间而言。 二、解题思路 根据题目范围&#xff0c…

SAP从入门到放弃系列之QM动态修改(Dynamic Modification)

目录 一、 概念二、系统操作 一、 概念 结合样本确定&#xff0c;动态修改也发挥着重要作用。根据先前检验的结果&#xff0c;动态修改会自动减少或增加 样本的大小。设置一定的规则&#xff0c;可以减少或增加检验中涉及的工作&#xff0c;也可节约检验成本。但是注意这种情况…

工业相机常见的工作模式、触发方式

参考&#xff1a;机器视觉——工业相机的触发应用(1) - 知乎 工业相机常见的工作模式一般分为&#xff1a; 触发模式连续模式同步模式授时同步模式 触发模式&#xff1a;相机收到外部的触发命令后&#xff0c;开始按照约定时长进行曝光&#xff0c;曝光结束后输出一帧图像。…

傅立叶级数的意义--傅立叶级数是怎么来的

写这篇文章的起因是14年有道题目&#xff1a; 本题实质上是考察傅立叶级数的意义&#xff0c;因此要求扩大为不能只拘泥于傅里叶级数的计算相关问题&#xff0c;故作此篇。 一、课本上的内容 傅立叶级数&#xff1a; 设函数 f ( x ) f(x) f(x)是周期为 2 l 2l 2l的周期函数&…

Python中的split()函数

函数&#xff1a;split() Python中有split()和os.path.split()两个函数&#xff0c;具体作用如下&#xff1a; split()&#xff1a;拆分字符串。通过指定分隔符对字符串进行切片&#xff0c;并返回分割后的字符串列表&#xff08;list&#xff09; os.path.split()&#xff1a…

汇总下之RobotFramework自动化框架的系列文章

总下之前分享的RobotFramework自动化框架的系列文章&#xff0c;有需要的同学可关注收藏 python自动化测试框架RobotFramework基础环境安装/使用&#xff08;一&#xff09; python自动化测试框架RobotFramework内置库BuiltIn介绍&#xff08;二&#xff09; python自动化测…

应用案例|基于三维机器视觉的机器人引导电动汽车充电头自动插拔应用方案

Part.1 项目背景 人类对减少温室气体排放、提高能源效率以及减少对化石燃料的依赖&#xff0c;加速了电动汽车的普及&#xff0c;然而&#xff0c;电动汽车的充电依然面临一些挑战。传统的电动汽车充电通常需要人工干预&#xff0c;插入和拔出充电头&#xff0c;这不仅可能导致…

计算机中了faust勒索病毒怎么办,faust勒索病毒解密,数据恢复

近年来网络技术得到了飞速发展&#xff0c;为人们的企业生产生活提供了极大便利&#xff0c;但随之而来的网络安全威胁也不断增加&#xff0c;近期&#xff0c;云天数据恢复中心收到了很多企业的求助&#xff0c;企业的计算机服务器遭到了faust勒索病毒攻击&#xff0c;导致企业…

Vue3.0插槽

用法&#xff1a; 父组件App.vue <template><div><!--将html代码插入到子组件中带默认名称的插槽中--><AChild><!--这段html会插入到AChild组件中<slot></slot>插槽中--><!-- 注意&#xff1a;写在父组件中的html代码只能在父组…

ubuntu 18.04 编译安装flexpart 10.4(2023年) —— 筑梦之路

2023年10月29日 环境说明 操作系统版本&#xff1a;ubuntu 18.04 python版本&#xff1a;3.6.9 gcc版本&#xff1a;7.5.0 编译安装路径&#xff1a;/usr/local cmake: 3.10.2 所需要的源码包我已经打包放到我的资源。 2021年1月份已经写过一篇Ubuntu 编译安装的帖子F…