Android 自动化测试 Espresso篇:简介基础使用
前言
最近在尝试深入学习Android单元测试。
以前笔者对于单元测试的理解很简单,做一个简单的API测试获取Server端数据,或者测试对应简单的工具类和数据处理的逻辑。
经过这近一个月的碎片化学习,深深了解到了单元测试的重要性,想找个机会总结一下,但是网上很多前辈都已经做出了更精辟的总结:
@小创作:为什么要做单元测试
更多理由不系表,如果有机会,笔者会专门写一篇关于对于单元测试浅陋的理解以及单元测试在开发中的重要性。个人认为项目中添加单元测试的优势有:
方便重构
节约时间
- 提升代码设计
在AndroidStudio2.2+的版本,新建的Project中会自动为开发者添加Espresso自动化测试库的依赖:
这说明谷歌官方也十分推崇开发者在开发时通过Espresso进行自动化测试,从而提高开发效率,我们作为Android开发者,也有必要去抽时间去了解一下其优势.
顺便提一句,AndroidStudio2.3+的版本中,细心的同学可以发现,新建的Project中会为开发者添加ConstraintLayout(约束布局)的依赖,该布局大幅提升了xml文件UI绘制的速度,并且避免了多层布局嵌套的苦手。有兴趣的同学可以去了解一下。
笔者的Android单元测试相关系列:
Android单元测试:Mockito使用详解
Android单元测试:使用本地数据测试Retrofit
Android单元测试:测试RxJava的同步及异步操作
Android 自动化测试 Espresso篇:简介&基础使用
Android 自动化测试 Espresso篇:异步代码测试
全副武装!AndroidUI自动化测试在RxImagePicker中的实践历程
一.简介,我们为什么使用Espresso
Espresso 是在2013年的 GTAC 上首次提出,目的是让开发人员能够快速地写出简洁,美观,可靠的 Android UI 测试。
举个简单的例子,我们这边有一个功能,点击界面Button,网络请求加载图片,正常开发人员想测试,需要:
点击run -> gradle build -> install apk -> 手动点击按钮 ->本人监测结果
其实并不麻烦,但是考虑一下,如果每个版本发布前都需要这么多次测试,或者我们简单修改了一下代码,那么我们需要再次进行以上步骤,并监测结果,来来往往,反反复复,实在是子子孙孙无穷匮也!
如果使用Espresso,我们只需要运行代码,代码会自动帮助我们执行这些流程(点击按钮)并且监测结果(是否加载到对应图片):
可以看到上面实际上,安装,进入界面,点击按钮,加载图片,判断结果,都是自动化的测试,不需要开发者去人为监测。
其实相比较于单元测试,Espresso我个人理解更倾向于像自动化集成测试,因为这个库实质上是开发者进行测试的时候,在测试设备上面安装了两个apk(开发者一般的apk和AndroidTest apk),然后模拟操作(比如点击按钮,滑动列表等等)在界面上,将开发者预期的结果和实际的结果进行对比。
二.Espresso测试 对比 单元测试(UnitTest)
这和单元测试(UnitTest)实际上是有本质的区别的,首先我们并不推荐单元测试中有真正的网络数据交互,通常我们的方式是本地mock一个模拟数据,然后进行测试。
其次,单元测试的功能一定是要单一的,并且是最基础的一个单元,测试的功能越单一,耦合度越低越好。这样如果我们需要测试一个复杂的功能,只需要把数个单一功能的模块分别测试,只要这些小模块都没有问题,组合出来的复杂功能自然也就不会出现什么问题了。
但是Espresso最强大的功能是UI界面的自动化测试,不可否认它支持异步请求(网络请求,数据库操作),但是成本过于高昂(需要大量的代码,而且需要实现idlingResource接口,这个后文再提)。
同时,Espresso需要依赖Android设备.这将导致我们将花费更多时间在编译apk和AndroidTest apk的安装上(即使已经比一般的手动测试快了很多倍)。
最后,它的耦合度看起来确实很大,正常我们项目的需求不可避免的都需要网络请求,那么我们简单的测试点击按钮,实际上还测试到了网络请求,图片加载等等,这样一个测试用例,实际上耦合了很多的功能,这不符合单元测试的思想。
但是Espresso一无是处了吗?并非如此。
转机
我们前文提到了,Espresso最强大的功能就是UI自动化测试,这是其他单元测试框架达不到的,所以我们完全可以通过Espresso进行界面数据展示的功能测试。
简而言之,我们可以让Espresso处理它拿手的UI界面测试,而网络请求等业务处理,我们可以交给其他测试框架去处理,比如Mockito(后文再讲)。
这里我们就要提到经典的MVP设计模式,MVP模式将数据的展示处理交给了View,业务代码交给了Model,我们完全可以通过MVP模式,将测试代码分开来测试,这样我们的问题就解决了。
说了这么多,不要好高骛远,笔者的意思是Espresso是值得Android开发人员花费时间成本去学习的,接下来做一个简单的案例,了解一下Espresso的简单使用。
三.Hello Espresso!
我们先来看一下我们的需求:
很简单,可以分为两个功能:
1,点击登录按钮,显示登陆成功Success,同时清空输入框
2,点击修改内容,显示hello espresso!
1.基础代码
看一下基本代码,很简单:
xml,布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".a_espresso.a01_simple.A01SimpleActivity"><LinearLayout
android:layout_width="0dp"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"><Button
android:id="@+id/btn01"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="修改内容" /><TextView
android:id="@+id/tv_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:visibility="gone" /><EditText
android:id="@+id/et_01"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="请输入账户名"android:text="123456"/><Button
android:id="@+id/btn02"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="登录" /></LinearLayout></android.support.constraint.ConstraintLayout>
Activity中对点击事件的处理:
@OnClick({R.id.btn01, R.id.btn02})public void onViewClicked(View view) {switch (view.getId()) {case R.id.btn01://显示hello espresso!tvContent.setVisibility(View.VISIBLE);tvContent.setText("hello espresso!");break;case R.id.btn02://登陆成功并且清空输入框tvContent.setVisibility(View.VISIBLE);tvContent.setText("success");et01.setText("");break;}}
2.测试代码
在你的AndroidTest目录下创建一个测试类,名字无所谓,但是为了规范我起名为Activity全名+Test:
比如MainActivity -> MainActivityTest
这样一目了然,见名知意。
测试类代码如下,有注解相信并不难理解:
@RunWith(AndroidJUnit4.class)
public class A01SimpleActivityTest {@Rule public ActivityTestRule<A01SimpleActivity> rule = new ActivityTestRule<>(A01SimpleActivity.class);@Test public void clickTest() {//tvContent是否默认不显示onView(ViewMatchers.withId(R.id.tv_content)).check(matches(not(isDisplayed()))); //是否不可见//检查btn01的text,然后执行点击事件onView(withId(R.id.btn01)).check(matches(withText("修改内容"))).perform(click());//检查tv内容是否修改,并且是否可见onView(withId(R.id.tv_content)).check(matches(withText("hello espresso!"))).check(matches(isDisplayed()));}@Test public void loginTest() throws Exception {//先清除editText的内容,然后输入,然后关闭软键盘,最后校验内容//这里如果要输入中文,使用replaceText()方法代替typeText()onView(withId(R.id.et_01)).perform(clearText(), replaceText("你好 username"), closeSoftKeyboard()).check(matches(withText("你好 username")));//点击登录onView(withId(R.id.btn02)).perform(click());//校验内容onView(withId(R.id.tv_content)).check(matches(withText("success"))).check(matches(isDisplayed()));onView(withId(R.id.et_01)).check(matches(withText(""))) //内容是否为"".check(matches(withHint("请输入账户名"))) //hint内容是否为"请输入账户名".check(matches(withHint(containsString("账户名")))); //hint内容是否包含"账户名"Thread.sleep(3000);}
}
需要注意的是,因为我们实际上有两个功能要测试,所以笔者建议最好每个功能分开写一个Test方法。
比如该测试类中,clickTest()测试点击显示Espresso,loginTest()测试登陆功能。
当然所有功能写一起也可以,但是这样本身就不太符合我们对测试的定义,多写几个测试方法,保证每个方法只涉及一个功能。这样才符合单元测试的粒度。
我们随便选择一个功能,以loginTest为例,运行测试代码(录屏有所瑕疵,见谅!):
查看结果:
测试通过。
总结
本文介绍了Espresso的实用性,同时通过了一个简单的入门案例,了解了Espresso的基本使用方式,如果对于Espresso某个方法不理解,还请查阅相关API文档:
Espressp 谷歌官方使用文档
建议不熟悉的同学上手一遍,基本就能了解了,本身Espresso的方法可以称得上是见文知意了。
本系列的所有代码都已托管 GitHub,点击查看.
下一篇文章,我们将对Espresso的异步网络请求进行简单的学习,欢迎关注。
2018/8/3追加更新
关于UI自动化测试的如何实践,我将自己写的一个图片选择器 RxImagePicker 进行了自动化测试的全面覆盖,希望能够给尝试Espresso的开发者一些经验参考,其效果:
我需要做的就是一遍惬意喝茶,一遍等待自动化测试的结果,很快,我得到了下面的结果:
关于 RxImagePicker UI自动化测试的实践历程,请参考我的这篇文章,希望对一些想要学习Espresso的朋友有一定的帮助:
全副武装!AndroidUI自动化测试在RxImagePicker中的实践历程
Android 自动化测试 Espresso篇:简介基础使用相关推荐
- Android自动化测试第一季(基础篇)-金阳光-专题视频课程
Android自动化测试第一季(基础篇)-32195人已学习 课程介绍 Android自动化测试第一季 初级 课程收益 零基础 讲师介绍 金阳光 更多讲师课程 ...
- Android自动化测试-Appium篇(二)
Android自动化测试-Appium篇(二) 基于Appium的Android自动化测试环境部署 1. 安装Appium Desktop: a.访问Appium官网:http://appium.io ...
- Android自动化测试工具—Monkey简介及入门
下面介绍下monkey的原理 Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中.它向系统发送伪随机的用户事件流(如按键输入.触摸屏输入.手势输入等),实现对正在开发的应用 ...
- Android自动化测试Uiautomator--UiSelector接口简介
UiSelector对象可以理解为一种条件对象,描述的是一种条件,可以配合UiObject使用得到某个符合条件的控件对象. 所有的方法都是public的,且都返回UiSelector类的对象. 文本方 ...
- 腾讯Android自动化测试实战
腾讯Android自动化测试实战 丁如敏 盛娟 等著 图书在版编目(CIP)数据 腾讯Android自动化测试实战 / 丁如敏等著. -北京:机械工业出版社,2016.10 ISBN 978-7-11 ...
- Android 系统(243)---Android进程系列第一篇---进程基础
Android进程系列第一篇---进程基础 内容预览.png 概述: 本文主要讲解进程基础,更深入的认识有血有肉的进程,内容涉及进程控制块,信号,进程FD泄露等等.仅供参考,欢迎指正. 一.从Linu ...
- Android 自动化测试框架简介
Android常用的自动化测试工具框架: Monkey,MonkeyRunner,UIAutomator,Robotium,Appium,Monkey Talk...... 但这些工具框架都是什么呢有 ...
- Android 音视频开发之基础篇 使用 SurfaceView绘制一张图片
Android 音视频开发 上一篇文章:使用 imageview绘制一张图片 任务一 SurfaceView绘制一张图片 文章目录 Android 音视频开发 前言 一.surfaceview是什么? ...
- <Android开发> Android vold - 第二篇 vold 的main()函数简介
本系列主要介绍 Android vold,分为以下篇章 <Android开发> Android vold - 第一篇 vold前言简介 <Android开发> Android ...
最新文章
- Laravel框架学习 -- php artisan down/up
- php学习day9---数据库的基本知识
- php是音频吗,只要是用PHP和JS发布的HTML5是否可以播放音频?
- 润乾报表使用问题总结
- nodejs做中间层_nodejs做中间层,向后端取数据
- 拓端tecdat|R语言markov switching model马尔可夫转换模型研究商业周期
- 粒子群优化算法matlab实现,粒子群优化算法的MATLAB程序实现+源程序
- Nginx-详解其原理
- 程序员的一百万种变现方式 03,努力多赚零花钱
- 诚之和:年轻人的尽头,是回老家买房吗?
- PPT调整同一行字符间距的三种常用方法
- 【虚幻4】UMG组件的简介与使用(Common 常用组件篇)
- 在window系统上对web项目进行safair兼容测试
- 给你的网页加个二次元老婆吧
- 如何保护WordPress网站免受网络攻击?采取安全措施至关重要
- Dreamweaver CS 5 快捷键大全
- 250部世界公认的经典大片
- Java Socket正确读取数据姿势
- 普元应用服务器软件AppServer V7版本正式发布
- 变异系数(测算数据离散程度相对指标)