Android自动化测试--Espresso框架使用

且说正文之前,还是先说说Android单元测试的意义或者说为什么我们要进行Android的单元测试?

为什么要进行单元测试?

单元测试可以帮助我们程序员将bug消灭在萌芽期,为后续的集成测试减少时间.大家可以看一下这篇文章,可能会说服你:为什么要进行烦人的单元测试?

如果那篇文章还不能说服你,那我只能使用杀手锏了~~

大家可以去各大招聘网站上看看,大部分公司都要求开发人员会编写测试用例或使用框架或工具进行测试,并且大公司要求更甚.

这下还有什么好说的吗?单元测试是一个硬要求,即便你不喜欢单元测试,但是如果你想进入一个理想的公司,这是必备的一个技能,所以无论如何你都要去学习的,反正技多不压身嘛.

那么,如果你想学习单元测试,从什么地方找学习资源呢?

但不管是通过上面哪个途径,主要说的都是通过Espresso框架进行单元测试.

当然也有其他的一些测试框架,大家也可以去尝试,但是Espresso框架是google官方大力推荐的一套测试框架,所以无论如何都要学习一下的.另外,自Android Studio2.2版本开始,google就为Espresso框架内置了一个图形化界面,用来自动生成单元测试代码.在下一篇文章,我会介绍如何利用这种图形化界面进行单元测试代码的编写.

下面正式开始

首先第一步要做的就是集成Espresso测试环境,非常简单,在你要测试的Module的gradle里添加如下两个依赖:

testCompile ‘junit:junit:4.12‘

androidTestCompile ‘com.android.support.test.espresso:espresso-core:2.2.2‘, {
        exclude group: ‘com.android.support‘, module: ‘support-annotations‘
    }

第一个是junit依赖,这个依赖Android Studio一般都会默认配置,所以你只需要配置第二个依赖即可.

举个栗子:

@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityInstrumentationTest {

    @Rule
    public ActivityTestRule mActivityRule = new ActivityTestRule<>(
            MainActivity.class);

    @Test
    public void sayHello(){
        onView(withText("Say hello!")).perform(click());

        onView(withId(R.id.textView)).check(matches(withText("Hello, World!")));
    }
}

上面这段代码是android官网上面的,关于Espresso的原理我就不说了,我也讲不来,强行讲的话,也讲的太肤浅.想了解原理的可以去Google一把.

那么我们首先关注两个注解:

@Rule:

顾名思义,测试规则,官方的解释是你可以在该注解下引用一个规则或定义一个方法,而你引用或定义的就是测试规则,这样说可能不是很清楚,可以看该注解下面的一句话:

public ActivityTestRule mActivityRule = new ActivityTestRule<>(
            MainActivity.class);

这句话就定义了一个测试规则,可以看到构造方法的参数里指定了一个 MainActivity.class,具体的体现就是当你运行这段测试代码时,app将会直接打开 MainActivity界面然后进行你所定义的测试用例.所以当你想直接测试某个界面时,你可以把那个界面填到这个参数里,这样就直接打开你指定的界面进行测试了.

@Test:

该注解用来定义一个测试用例,当你的测试类运行时,所执行的代码就是Test注解下的(Espresso还提供了其他的一些注解,比如:@After,@Before等,具体的用法可以去我上面写的android官网上查看),当然上面那段代码对应的就是sayHello测试方法,sayHello方法里所定义的就是要测试的内容,该内容的含义为:

onView(withText("Say hello!")).perform(click());

含义:根据文本”Say hello!”找个这个控件然后执行该控件的点击方法.

onView(withId(R.id.textView)).check(matches(withText("Hello, World!")));

含义:根据id “textView”找到这个控件然后检查该控件上面显示的文本是不是”Hello, World!”.

是不是很容易理解?非常语义化,一般都能看的懂.Espresso还提供了其他的方法供我们测试时调用,下面会列举一些常用的.

但是在列举常用的方法之前,需要先说明几点Espresso的注意事项,不然当你测试的时候会因为Espresso报的各种错误气个半死!!!

  • 无论是通过withId()找控件还是通过withText()找控件或者其他方式比如withClassName(),withResourceName(),withTagKey()等方法,都要一定保证你所找的控件在当前页面确实存在且可见,不然会报:NoMatchingViewException,当然你可能还会碰到其他异常,比如AmbiguousViewMatcherException,AppNotIdleException异常等等,具体的报错原因可以到android官网查看,地址如下:Espresso的各种异常
  • 如果你要测试AdapterView ,比如 ListView 或GridView等,使用上面的onView()方法是无效的,因为AdapterView的布局item是动态呈现的,没法直接指定,所以当你要测试AdapterView时,请把onView()方法换成onData() 方法,与onView()方法返回ViewInteraction类似,onData()方法返回DataInteraction,二者用法基本都是一样的.

perform()参数中常用的方法:

在上面的一段官网代码中,我们用到了perform(click()),那么除了click()方法还有其他功能强大的方法可以供我们使用,下面列举一些常用的方法:

  • click():

    返回一个点击action,Espresso利用这个方法执行一次点击操作,就和我们自己手动点击按钮一样,只不过Espresso把点击这个操作自动化了,下面的方法都是一样的道理,就不再赘述了.

  • clearText():

    返回一个清除指定view中的文本action,在测试EditText时用的比较多

  • swipeLeft():

    返回一个从右往左滑动的action,这个在测试ViewPager时特别有用

  • swipeRight():

    返回一个从左往右滑动的action,这个在测试ViewPager时特别有用

  • swipeDown():

    返回一个从上往下滑动的action

  • swipeUp():

    返回一个从下往上滑动的action

  • closeSoftKeyboard():

    返回一个关闭输入键盘的action

  • pressBack():

    返回一个点击手机上返回键的action

  • doubleClick():

    返回一个双击action

  • longClick():

    返回一个长按action

  • scrollTo():

    返回一个移动action

  • replaceText():

    返回一个替换文本action

  • openLinkWithText():

    返回一个打开指定链接action

除了以上的常用方法还有其他一些不常用的,想继续研究的可以查看Espresso中的ViewActions类,需要注意的是,所有的方法包括上面说到的和没说到的,都有一个必须的前提条件,就是你要执行的view必须在当前界面上显示出来,这有两层意思:

1,当前界面必须能找到这个控件

2,这个控件必须是可见的

这是以上所有方法中通用的要求,当然有些方法还有额外的要求,比如必须要先获取焦点等,

说到这里,我们梳理一下我们学习了哪些东西:

1,如何根据id或文本或其他方法找到具体控件

2,如何让这个控件执行相关操作

3,一些使用注意事项

所以,现在我们完全可以自己写一个完整的测试用例了.

先来个gif图:

上面的动图测试的流程为:打开软件,滑动Viewpager的3个页面,在最后一个页面点击开始体验按钮进入主界面,点击预约叫车,由于没有登录所以会跳转到登陆页面,输入手机号,然后点击获取验证码按钮,然后输入验证码,最后点击登陆.

整个流程对应的代码测试代码如下:

@LargeTest
@RunWith(AndroidJUnit4.class)
public class StartActivityTest {

    @Rule
    public ActivityTestRule<StartActivity> mActivityTestRule = new ActivityTestRule<>(StartActivity.class);

    @Test
    public void startActivityTest() {
        //根据id找到ViewPager页面,并判断是否可见
        ViewInteraction appCompatViewPager = onView(
                allOf(withId(R.id.viewPager), isDisplayed()));
        // 向左滑动viewpager页面,下面3句也可以写成一句话,Espresso会从左到右依次执行
        // appCompatViewPager.perform(swipeLeft(),swipeLeft(),swipeLeft());
        appCompatViewPager.perform(swipeLeft());
        appCompatViewPager.perform(swipeLeft());
        appCompatViewPager.perform(swipeLeft());
        //根据文本找到"开始体验"按钮,并判断是否可见
        ViewInteraction appCompatButton = onView(
                allOf(withText("开始体验"), isDisplayed()));
        //执行按钮的点击操作
        appCompatButton.perform(click());
        //根据控件的id和该控件的父布局id找到控件,并判断是否可见
        ViewInteraction appCompatImageView = onView(
                allOf(withId(R.id.appointmentCallCar), withParent(withId(R.id.callCarLayout)), isDisplayed()));
        //执行该控件的点击操作
        appCompatImageView.perform(click());
        //根据id找到控件,并判断是否可见
        ViewInteraction appCompatEditText = onView(
                allOf(withId(R.id.phoneNumber), isDisplayed()));
        //执行替换文本操作,说白了就是输入文本,输入完毕之后关闭输入法键盘
        appCompatEditText.perform(replaceText("18894001263"), closeSoftKeyboard());
        //根据id和显示的文本内容找到控件,并判断是否可见
        ViewInteraction appCompatButton2 = onView(
                allOf(withId(R.id.getPassword), withText("获取验证码"), isDisplayed()));
        //执行该控件的点击操作
        appCompatButton2.perform(click());
        //根据id找到控件,并判断是否可见
        ViewInteraction appCompatEditText2 = onView(
                allOf(withId(R.id.password), isDisplayed()));
        //执行替换文本操作,说白了就是输入文本,输入完毕之后关闭输入法键盘
        appCompatEditText2.perform(replaceText("2454"), closeSoftKeyboard());
        //根据id和显示的文本内容找到控件,并判断是否可见
        ViewInteraction appCompatButton3 = onView(
                allOf(withId(R.id.login), withText("登录"), isDisplayed()));
        //执行该控件的点击操作
        appCompatButton3.perform(click());
    }
}

这里还需要说明一点,当所有的测试用例执行完毕之后,Espresso会自动关闭界面,根据动图也可以看到,当点击完登陆按钮之后,又回到了系统屏幕界面.

当测试完毕之后,在Android Studio的”Run”控制台可以看到测试结果,如下图:

如果测试顺利通过,会在下图中左侧显示All Test Passed:

如果测试没有通过,则会在右侧的控制台中输入错误信息,我们可以根据这些错误信息修改我们的代码然后再次进行测试.

以上的测试代码只是测试了启动和登陆功能,可以看到,套路都是一样的:根据id或文本等条件找到控件,然后执行控件的相关操作,这些代码都是重复的,唯一变化的就是执行的操作和查找的条件不一样,我们试想一下,如果项目一旦很大,我们一个一个手动的编写测试代码是不是很麻烦,并且都是一样的套路,没有一点技术含量.如果有种方式能自动生成这些测试代码,而我们只需要根据具体的测试情况修改甚至不改这些自动生成的代码就能完成测试,是不是就可以极大的节省我们的时间?而恰好Android Studio2.2版本提供了一个使用Espresso框架进行测试的图形化界面–Record Espresso Test功能,通过这个功能,我们只需要把软件运行到真机或模拟器上,然后就可以像平常手动测试软件一样,按照业务逻辑点击/滑动即可,Record Espresso Test功能会自动生成相应的测试代码,我们运行生成的测试代码,Espresso就可以自动的按照我们刚才操作的顺序自动的完成测试,是不是很方便啊.关于如何使用Record Espresso Test功能,以后会单独写一篇文章来说明,其实操作起来也很简单,大家可以先自己去尝试一下.

时间: 2024-10-31 21:44:47

Android自动化测试--Espresso框架使用的相关文章

Android 自动化测试框架

Android常用的自动化测试工具框架: Monkey,MonkeyRunner,UIAutomator,Robotium,Appium,Monkey Talk 但是这些工具框架都有什么关系呢,先通过一张图来了解一下吧.(图是某博客上借过来的) 是不是一脸懵逼,不知道这是什么鬼.下面详细了解一下. 一.Monkey 是Android SDK自带的测试工具,是一个命令行工具,可以运行在模拟器中或者实际设备中,它向系统发送伪随机的用户事件流(如按键输入,触摸屏输入,手势输入等),实现对正在开发的应用

Android自动化测试框架开发(一)自动化测试框架概要

在做Android自动化测试框架开发之前,我们应该先了解目前的发展状况,知道我们的目标是什么,也要了解当前的主流框架,做到知己知彼,取长补短. 首先要思考和了解几个问题: 我们开发自动化框架的目标是什么?如何得到想要的框架? 目前主流自动化框架的优劣势分析 剖析主流自动化框架的源码 如何利用框架进行二次开发? 本篇文章介绍上述第一个问题: 一:Android自动化测试框架目标 稳定性好:尽可能使用开发人员对控件定义的id等唯一定位信息,减少通过控件index进行节点判断 可移植性好:尽可能减少通

Android自动化测试框架分析

摘自<深入理解Android自动化测试>作者:许奔 1. 稳定性好:尽可能少地通过控件index进行节点判断. 2.可移植性好:尽可能少地通过坐标进行控件定位. monkey.monkeyrunner通过坐标进行控件定位. 3. 支持多应用交互:框架必须支持跨应用. instrumentation不支持跨应用. 4. 运行效率高:窗口跳转监控和窗口定位要准确. monkey.monkeyrunner窗口跳转监控和窗口定位不准确. 5. 容易上手:框架接口要容易理解和掌握. monkeyrunn

Android开源测试框架学习

近期因工作需要,分析了一些Android的测试框架,在这也分享下整理完的资料. Android测试大致分三大块: 代码层测试 用户操作模拟,功能测试 安装部署及稳定性测试 代码层测试 对于一般java代码,采用传统的Junit测试,开发人员通常会编写重要接口和函数的白盒测试代码,不做过多讨论. 但因Android的特殊运行机制(Dalvik虚拟机),其中存在Application.Activity.Service等特殊组件,而这些组件都涉及到生命周期管理的问题. 为了对这些组件进行测试,Goog

Android自动化测试工具实现简述

前言 自动化测试在产品开发和测试中都有着非常重要的作用.在产品开发阶段,可靠又重复性地运行以确保没有引进回归问题:在产品测试阶段,可以节省人力成本和时间成本,并能保证更大范围的覆盖.Android自动化测试工具同样可以节省不少人力和时间成本,对其研究和实现对于提高测试效率具有一定的意义.目前市面上也有不少Android自动化测试工具,本人在现有工具的基础上,加上自己的理解和实践向大家介绍自动化测试工具的原理和实现. 了解自动化测试的一定对Robotium并不陌生,Robotium是一款国外的An

Android 自动化测试(3)&lt;monkeyrunner&gt; 根据ID查找对象&amp;touch&amp;type (python)

我在之前的两篇文章中用java来实现过 Android 自动化测试(1)如何安装和卸载一个应用(java).Android 自动化测试(2)根据ID查找对象(java). 但是本质上都是用monkeyrunner对应的java lib 来实现的,但是相关的文档非常少,如果真的要用monkeyrunner来做功能性的自动化测试,强烈还是推荐使用python语言 1.monkey runner The monkeyrunner tool provides an API for writing pro

Android 自动化测试(5)&lt;robotium&gt;

关于Android的自动化测试之UI测试,之前介绍过Android 自动化测试(4)<uiautomator>, 在android原生的单元测试框架上,利用uiautomator.jar这个类库来完成Android的界面上的测试,这已经使得测试比较简单了.但还有更加简单的写测试的方式,那就是利用一些第三方的测试框架,比如robotium. Android的第三方的测试框架,有Robolectric 和 robotium,我试着用了下,觉得robotium已经非常好用了. 1.概要 Roboti

简析Android 兼容性测试框架CTS使用

一.什么是兼容性测试? 1)为用户提供最好的用户体验,让更多高质量的APP可以顺利的运行在此平台上 2)让程序员能为此平台写更多的高质量的应用程序 3)可以更好的利用Android应用市场 二.CTS覆盖领域 1)签名测试:针对每个Android正式版,都将附带一系列XML文档对所有的公共API签名进行描述.CTS将检查这些签名是否适用于该设备,并保存其结果. 2)平台API测试:测试SDK中平台核心库和Android应用程序框架的API是否正确 3)Dalvik虚拟机测试:集中测试Dalvik

25类Android常用开源框架

1.图片加载,缓存,处理 框架名称 功能描述 Android Universal Image Loader 一个强大的加载,缓存,展示图片的库,已过时 Picasso 一个强大的图片下载与缓存的库 Fresco 一个用于管理图像和他们使用的内存的库 Glide 一个图片加载和缓存的库,使用的App有:网易新闻 GlidePalette Android Lollipop Palette is now easy to use with Glide PicassoPalette Android Lol