iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >解放双手,Android开发应该尝试的UI自动化测试
  • 642
分享到

解放双手,Android开发应该尝试的UI自动化测试

ui自动化测试android开发测试Android 2022-06-06 13:06:07 642人浏览 八月长安
摘要

前言 人们懒的走路,才创造了汽车;  人们懒的爬楼,才创造了电梯;  人们懒的扫地,才创造了自动扫地机器人。  人类的进步,离不开这些喜欢偷懒的人,Google希望,当Andr

前言

人们懒的走路,才创造了汽车; 
人们懒的爬楼,才创造了电梯; 
人们懒的扫地,才创造了自动扫地机器人。 
人类的进步,离不开这些喜欢偷懒的人,Google希望,当Android开发者利用Espresso写完测试用例后,能一边看着测试用例自动执行,一边享受一杯香醇Espresso(浓咖啡)。

为什么要单元测试

@小创作:为什么要做单元测试

为什么要进行烦人的单元测试?

以下引用Android官方文档对测试的概述

测试应用是应用开发过程中不可或缺的一部分。通过持续对应用运行测试,您可以在公开发布应用之前验证其正确性、功能行为和易用性。

测试还会为您提供以下优势:

快速获得故障反馈。 在开发周期中尽早进行故障检测更安全的代码重构,让您可以优化代码而不必担心回归。 稳定的开发速度,帮助您最大限度地减轻技术负担。 关于 Espresso

Espresso 是 Google 开源的一款 Android 自动化测试框架,目标是让开发人员能够快速地写出简洁、美观且可靠的 Android 界面测试,特点如下:

规模更小、更简洁,api更加精确,编写测试代码简单,容易快速上手。

提供了自动同步操作,在主线程空闲的时候,运行测试代码,从而提高测试的可靠性。

可以运行在Android2.3.3及其更高版本。

因为是基于Instrumentation的,所以不能跨App。

环境配置

作为Google的亲儿子,难免会对其照顾有加,相信有一些朋友已经知道在AndroidStudio2.2版本之后,在新建的项目中,AndroidStudio会默认添加Espresso的依赖。

添加依赖

在build.gradle
 文件中添加如下依赖:

androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
//espresso-contrib扩展包用于RecyclerView相关操作,不需要可以不用添加
androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.0') {
    exclude group: 'com.android.support', module: 'appcompat'
    exclude group: 'com.android.support', module: 'support-v4'
    exclude module: 'recyclerview-v7'
    //不导入依赖中的包,避免出现依赖冲突,使用用户自己导入的包
}

除此之外Espresso还有一些扩展包,用于完成一些特殊的测试场景:

espresso-core
 - 包含核心和基本的 
View
 匹配器、操作和断言。
espresso-WEB
 - 包含 
WebView
 支持的资源。
espresso-idling-resource
 - Espresso 与后台作业同步的机制。
espresso-contrib
 - 外部贡献,包含 
DatePicker
RecyclerView
 和 
Drawer
 操作、无障碍功能检查以及 
CountingIdlingResource
espresso-intents
 - 用于对封闭测试的 intent 进行验证和打桩的扩展。

espresso-remote
 - Espresso 的多进程功能的位置。

设置 instrumentation runner

build.gradle
 文件的 
android.defaultConfig
 中添加如下配置:

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
设置测试环境

为了避免测试不稳定,建议在用于测试的虚拟或物理设备上关闭系统动画,在设置 > 开发者选项下,停用以下三项设置:

窗口动画缩放 过渡动画缩放 Animator 时长缩放 Espresso 基本使用

三步曲

ViewMatchers – 寻找View。 ViewActions – 执行交互事件。 ViewAssertions – 检验测试结果。

示例:

onView(withId(R.id.my_view))      // withId(R.id.my_view) is a ViewMatcher
  .perfORM(click())               // click() is a ViewAction
  .check(matches(isDisplayed())); // matches(isDisplayed()) is a ViewAssertion
Espresso 测试代码位置和静态导入

Espresso 测试代码放在 app/src/androidTest 目录下。

为了简化 Espresso API 的使用, 建议使用以下静态导入. 可以允许在没有类前缀的前提下访问这些静态方法。

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.Espresso.pressBack;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
寻找 View ViewMatchers
函数 功能
assertThat() 用于生成断言描述的工具
hasContentDescription() 匹配具有内容描述的view
hasDescendant() 匹配具有特定子视图(直接或间接)的view
hasErrorText() 匹配getError为特定字符串的EditView
hasFocus() 匹配获取焦点的view
hasImeAction() 匹配支持输入,并且具有特定IMEAction的view
hasLinks() 匹配具有超链接的TextView
hasSibling() 匹配具有特定相邻view的view
isAssignableFrom() 匹配继承自特定类的view
isChecked() 匹配实现Checkable接口并且处于选中状态的View
isClickable() 匹配可以点击的view
isCompletelyDisplayed() 匹配全部显示在视图中的view
isDescendantOfA() 匹配具有特定父视图(直接或间接)的view
isDisplayed() 匹配显示在视图中(包括部分)的view
isDisplayingAtLeast() 匹配显示在视图中超过指定比值的view
isEnabled() 匹配当前可用(非灰色)的view
isFocusable() 匹配可以获取焦点的view
isjavascriptEnabled() 匹配开启js的webView
isNotChecked() 匹配实现Checkable接口并且处于未选中状态的View
isRoot() 匹配本身为root的view
isSelected() 匹配被选中的view
supportsInputMethods() 匹配支持输入的View
withChild() 匹配具有特定直接子视图的view
withClassName() 匹配具有特定类名的view
withContentDescription() 匹配具有特定内容描述的view
withEffectiveVisibility() 匹配显示在屏幕上(所有父视图为Visible)的view
withHint() 匹配getHint为指定字符串的TextView
withId() 匹配具有指定id的view
withInputType() 匹配具有指定输入类型的EditView
withParent() 匹配具有特定直接父视图的view
withResourceName() 匹配具有指定资源名称的view
withSpinnerText() 匹配getSeletedItem为指定文本的view
withTagKey() 匹配getTag为指定值的view
withText() 匹配getText为指定字符串的TextView
RootMatchers
函数 功能
isDialog() 匹配是对话框的root
isFocusable() 匹配拥有焦点的root
isPlatformPopup() 匹配是弹出窗的root
isTouchable() 匹配可以触摸的root
withDecorView() 匹配满足特定条件的root
Matchers
函数 功能
allOf() 将所有matcher合并为一个matcher(必须满足所有matcher)
any() 生成一个判定是否为指定类实例或者子类的matcher
anyOf() 将所有matcher合并为一个matcher(满足至少一个matcher即可)
anything() 生成一个匹配任何对象的matcher(matches写死返回值为true)
array() 由n个matcher生成一个可以对应匹配array[n],中每个data的matcher(必须依次对应)
arrayContaining() 由n个data生成一个可以对应匹配array[n],中每个data的matcher(必须依次对应)
arrayContainingInAnyOrder() 由n个data生成一个可以对应匹配array[n],中每个data的matcher(不必依次对应)
arrayWithSize() 生成匹配指定array.size()的matcher
both() 将两个matcher合并成一个matcher
closeTo() 生成matcher匹配误差范围内的数:num∈[operand-error,operand+error]
comparesEqualTo() 生成matcher匹配指定value
contains() iterable中每一项符合对应matcher(必须依次匹配)
containsInAnyOrder() iterable中每一项符合对应matcher(不必依次匹配)
containsString() 包含特定string
describedAs() 更改matcher的描述
either() 指定对象与指定匹配器匹配时匹配
empty() collection为空
emptyArray() 数组为空
emptyCollectionOf() collection为空
emptyIterable() Iterable为空
emptyIterableOf() Iterable为空
endsWith() String以指定字符串结尾
equalTo() 封装equalTo
equalToIgnorinGCase() string.equalTo()忽略大小写
equalToIgnoringWhiteSpace() string.equalTo()忽略大小写和留白
eventFrom() 匹配从指定source中派生的eventObject
everyItem() Iterable中任何一项都符合目标matcher
greaterThan() 大于指定值
greaterThanOrEqualTo() 大于等于指定值
hasEntry() 匹配指定Map
hasItem() 匹配具有指定item的Iterable
hasItemInArray() 匹配具有指定item的数组
hasItems() 匹配具有指定多个item的Iterable
hasKey() 具有特定K 的Map
hasProperty() 具有指定名称成员变量的对象
hasSize() Collection为指定size
hasToString() 匹配toString为指定值的对象
hasValue() 具有特定V的Map
hasXPath() Creates a matcher of {@link org.w3c.dom.node}s that matches when the examined node contains a node at the specified
xPath
, with any content.
instanceOf() 为特定class的实例或者子类
is() 封装上文matcher:equalTo
isA() 封装上文matcher:instanceOf
isEmptyOrNullStringv() ""或者空String
isEmptyString() ""(String)
isIn() 匹配指定Array中的item
isOneOf() 匹配列举中的一项
iterableWithSize() iterable的size为指定值
lessThan() 小于特定值
lessThanOrEqualTo() 小于等于特定值
not() 不匹配指定matcher
notNullValue() 不为空值
nullValue() 空值
sameInstance() 对象相同的
samePropertyValuesAs() 具有相同属性值
startsWith() String以特定字符串开始
stringContainsInOrder() 具有特定一个字符串的String
theInstance() 对象相同的与上文sameInstance相同
typeCompatibleWith() 当前class是继承自指定class
执行交互事件 ViewActions
函数 功能
addGlobalAssertion() 设置全局断言
actionWithAssertions() 包装 action ,执行前必须满足所有全局断言
removeGlobalAssertion() 删除全局断言
clearGlobalAssertions() 清空全局断言
clearText() 清空文本
click() 单击
click(ViewAction rollbackAction() 单击(防止误判为长按)
closeSofTKEyboard() 关闭软键盘
doubleClick() 双击
longClick() 长按
openLink() 打开连接(TextView)
openLinkWithText() 打开连接(Text)
openLinkWithUri() 打开连接(Uri)
pressBack() 返回键
pressImeActionButton()  
pressKey() 根据Key模拟按键
preSSMenuKey() 实体键盘菜单键
replaceText() 替换文本
scrollTo() 滑动到
swipeDown() 下滑
swipeLeft() 左滑
swipeRight() 右滑
swipeUp() 上滑
typeText() 获得焦点并注入文本(模拟按键单个输入)
typeTextIntoFocusedView() 在已获得焦点的View上注入文本(模拟按键单个输入)
检验测试结果 ViewAssertions

这里用的最多的时 

matches(Matcher)
 ,可以根据自己的需求情况修改 Matcher 来变更断言。

函数 功能
doesNotExist() 断言目标 view 不存在于当前布局
matches() 断言当前 view 是否匹配指定 matcher
seletedDescendantsMatch() 目标 view 的子视图如果匹配第一个matcher,则一定匹配第二个
LayoutAssertions
函数 功能
noEllipsizedText() 布局不包含椭圆化或剪切的TextView
noMultilineButtons() 布局中不包含具有多行文本的Button
noOverlaps 与匹配的子视图不重叠
PositionAssertions
函数
isAbove(Matcher matcher)
isBelow(Matcher matcher)
isBottomAlignedWith(Matcher matcher)
isLeftAlignedWith(Matcher matcher)
isLeftOf(Matcher matcher)
sRightAlignedWith(Matcher matcher)
isRightOf(Matcher matcher)
isTopAlignedWith(Matcher matcher)
具体案例

TODO:未完待遇
进阶使用 onData的使用

对于

ListView
,如果要操作其中的某一个item,特别是不可见状态的item,是不能通过上述的
ViewMatch
来定位的。我们都知道
ListView
View
是复用的,不可见状态的item并没有把内容绘制到
View
上。Espresso针对
AdapterView
ListView
的父类),提供了
onData
来支持。

Idling Resource的使用


TODO:未完待遇
注意

避免

Activity
的层级跳转,测试用例尽量只在单个
Activity
内完成。
Activity
层级跳转越多,越容易出错
强烈不推荐,直接获取
View
的对象,调用
View
的方法来模拟用户操作。应该统一使用Espresso提供的方法
测试用例,特别是UI自动化测试用例,应该尽量保持逻辑简单,覆盖关键路径就足矣。因为UI变动是很频繁的,越复杂,维护成本就越高,投入产出比就会自然降低了。

感想

正如周报中所言,发现自己会和分享给别人完全是两回事,1.首先得让人认可这件事是有意义的 2.这件事用这种方案是最合适的 3.最后才是这个方案分享出去的每一个知识点是正确的。目前我只能做到第三点。

写在最后

引用官方介绍的一段话,Espresso的目标受众是开发者。希望更多的团队能够实现Google的期许最大化利用Espresso,把Bug扼杀在摇篮中。

引用
作者:clwwlc


--结束END--

本文标题: 解放双手,Android开发应该尝试的UI自动化测试

本文链接: https://www.lsjlt.com/news/29207.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • PHP开发中的单元测试与自动化测试
    php 中的单元测试和自动化测试至关重要,可确保代码可靠性。单元测试隔离测试代码单元,通过断言检查预期结果。自动化测试利用 ci 平台自动执行测试,确保代码持续满足质量标准,包括配置测试...
    99+
    2024-05-09
    自动化测试 单元测试 git
  • CMS插件开发 的自动化工具:解放开发者双手
    CMS(内容管理系统)插件是增强 CMS 功能和扩展其用途的附加组件。开发和维护这些插件通常是一项耗时且容易出错的任务。然而,借助 CMS 插件开发自动化工具,开发者可以大大简化和加速这一过程。 自动代码生成 自动化工具可以自动生成针对...
    99+
    2024-02-15
    CMS 插件 自动化 开发 工具
  • android AccessibilityService无障碍功能开发,实现自动化测试
    android AccessibilityService无障碍功能开发,实现自动化测试,这里使用抖音为例子,仅供技术研究学习使用。 使用方法 安装好APP后,需要打开无障碍功能,打开后,在次打开抖音APP,随便找一个直播间,上下滑动切换直接...
    99+
    2023-09-13
    android android studio java
  • 如何处理PHP开发中的单元测试和自动化测试
    随着软件开发行业的日益发展,单元测试和自动化测试成为了开发者们重视的环节。PHP作为一种广泛应用于Web开发的脚本语言,单元测试和自动化测试同样也在PHP开发中扮演着重要的角色。本文将介绍如何处理PHP开发中的单元测试和自动化测试,并提供一...
    99+
    2023-10-21
    自动化测试 单元测试 PHP开发
  • 移动开发中自动化测试的示例分析
    小编给大家分享一下移动开发中自动化测试的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、自动化测试的概念自动化测试是把以人为驱动的测试行为转化为机器执行...
    99+
    2023-06-04
  • Java反射的应用场景:从框架开发到自动化测试
    Java反射是一种能够获取类、方法、字段及其属性的强大技术,在框架开发、自动化测试、逆向工程等场景中发挥着重要作用。 1. 框架开发 借助反射,您可以构建可扩展且灵活的软件框架。通过反射,您可以发现和加载类,创建类的实例,调用类的方法,...
    99+
    2024-02-09
    Java 反射 框架开发 自动化测试 逆向工程
  • C++嵌入式系统开发的自动化测试实践
    自动化测试实践可提高嵌入式系统开发的质量、效率和可重复性。对于 c++++ 开发,google test 框架提供了丰富的断言、用例生成器和 ide 集成。实战案例演示了使用 googl...
    99+
    2024-05-12
    自动化测试 c++
  • 怎样解说AngularJS在自动化测试中的应用
    今天就跟大家聊聊有关怎样解说AngularJS在自动化测试中的应用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、什么是AngularJS AngularJS是一组用来开发web页...
    99+
    2023-06-05
  • 浅谈基于Pytest框架的自动化测试开发实践
    目录01 — Pytest核心功能02 — 创建测试项目03 — 编写测试用例04 — 执行测试用例05 — 数据与脚本分离06 — 参数化07 — 测试配置管理08 — 测试的准备...
    99+
    2024-04-02
  • 怎么实现android应用程序自动化测试的批处理脚本
    本篇内容介绍了“怎么实现android应用程序自动化测试的批处理脚本”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!测试平台:兼容androi...
    99+
    2023-06-08
  • 通过Go语言开发实现自动化测试的工具与框架
    通过Go语言开发实现自动化测试的工具与框架一、绪论随着软件开发的不断进步,自动化测试在保证软件质量和提高开发效率方面扮演着重要角色。而Go语言,作为一种简洁、高效、并发的编程语言,逐渐受到开发者们的喜爱。本文将介绍如何使用Go语言开发实现自...
    99+
    2023-11-20
    自动化测试 关键词:Go语言 工具与框架
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作