前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android单元测试框架Espresso介绍

Android单元测试框架Espresso介绍

作者头像
顾翔
发布2019-12-12 11:11:14
9610
发布2019-12-12 11:11:14
举报

顾翔老师开发的bugreport2script开源了,希望大家多提建议。文件在https://github.com/xianggu625/bug2testscript,

主文件是:zentao.py 。bugreport是禅道,script是python3+selenium 3,按照规则在禅道上书写的bugreport可由zentao.py程序生成py测试脚本。

大家都知道,测试Android系统原生态APP目前最好的工具使UiAutomation,随着DevOps的普及,我们需要尽早地发现程序中的缺陷,所以单元测试变得非常重要,Android系统推出了Espresso测试框架。Espresso与UiAutomation最显著区别在于UiAutomation可以测试一个APP多个界面(Active),而Espresso只能测试一个APP一个界面(Active),另外UiAutomation可以独立测试APP建立专门的Project,Espresso必须建立在待测APP同一个目录下。下面我向大家简单介绍一下Espresso。

进行Espresso,首先在待测APP的build.gradle(module.app)中作如下的配置。

代码语言:javascript
复制

android {

     …

     }

     buildTypes {

         release {

            minifyEnabled false

            proguardFiles  getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

         }

     }

     packagingOptions{

         exclude'LICENSE.txt'

     }

}

dependencies {

     …

     androidTestImplementation 'com.android.support.test:runner:0.5'

     androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2',  {

     exclude group: 'com.android.support', module: 'support-annotations'

     })}

这里特别需要注意的是:com.android.support.test:runner请使用0.5版本,最新的1.0版本有bug。

同步完成,我们在待测试代码的androidTest建立测试代码,下面是这段Espresso代码。

代码语言:javascript
复制
package com.example.espresso.demo4;

 

import  android.support.test.filters.LargeTest;

import  android.support.test.rule.ActivityTestRule;

import  android.support.test.runner.AndroidJUnit4;

 

import static  android.support.test.espresso.Espresso.onView;

import static  android.support.test.espresso.action.ViewActions.click;

import static  android.support.test.espresso.action.ViewActions.closeSoftKeyboard;

import static  android.support.test.espresso.action.ViewActions.replaceText;

import static  android.support.test.espresso.assertion.ViewAssertions.matches;

import static  android.support.test.espresso.matcher.RootMatchers.withDecorView;

import static  android.support.test.espresso.matcher.ViewMatchers.isDisplayed;

import static  android.support.test.espresso.matcher.ViewMatchers.withId;

import static  android.support.test.espresso.matcher.ViewMatchers.withText;

import static  org.hamcrest.core.StringStartsWith.startsWith;

import static org.hamcrest.Matchers.not;

 

import org.junit.Rule;

import org.junit.Test;

import org.junit.runner.RunWith;

 

@RunWith(AndroidJUnit4.class)

public class  MainActivityInstrumentationTest {

     private static final String username="Guxiang";

     private static final String password="123456";

     @Rule

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

 

     @Test

     @LargeTest

     public void testDemo4(){

         onView(withId(R.id.username)).perform(replaceText(username),closeSoftKeyboard());

onView(withId(R.id.password)).perform(replaceText(password),closeSoftKeyboard());

onView(withText("登录")).perform(click());

onView(withText(startsWith("用户名或密码")))

      .inRoot(withDecorView(not(mActivityRule.getActivity().getWindow().getDecorView())))

      .check(matches(isDisplayed()));

      //onView(withId(R.id.tv1)).check(matches(withText(expectedText)));

     }

}

这段代码实现的功能是,在登录页面输入错误的登录名或密码,点击【登录】案件后测试系统是否给出“用户名或密码”错误信息。

1、准备工作

package com.example.espresso.demo4;

首先保证测试代码的package与产品代码的package保持一致。

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

表示待测的是产品代码中的MainActivity.class模块,我们把测试模块变量赋给变量mActivityRule。

2、定位

onView(withId(R.id.username)).perform(replaceText(username),closeSoftKeyboard());

这段代码通过函数onView来执行操作,withId(R.id.username)是通过APP的R.id.username来进行定位,在这里id名为username,这里的R文件与产品代码中R.java中定义的。除了用withId定位外,还可以使用withText(String):元素的Text名,withClassName():元素的className名,withContentDescription():元素的描述信息等方法来定位。也可以采用多元素属性联合定位来实现,比如:

onView(allOf(withId(R.id.button_signin), withText("Sign-in")));

通过id为R.id.button_signin且Text为Sign-in的元素来定位。另外在定位中还可以使用no函数,表示“不”的意思,比如:

onView(allOf(withId(R.id.button_signin), not(withText("Sign-out"))));

id为R.id.button_signin但是Text不是Sign-in的元素。

除了用onView进行定位,也可以用onData进行定位。

onData(allOf(is(instanceOf(String.class)), is("Americano")));

假设一个Spinner的控件,我们要点击“Americano”,可用上面的语句来定位。同样假设是一个Listview,我们需要点击Listview中第二个item的按钮,那么我们需要这样写。

onData(Matchers.allOf()) .inAdapterView(withId(R.id.photo_gridview)) // listview的id .atPosition(1) // 所在位置 .onChildView(withId(R.id.imageview_photo)) // item中子控件id

3、操作

perform后面为对定位的元素执行操作,常用的方法有。

ViewActions.replaceText()

清空后输入

ViewActions.typeText()

点击事件输入指定的文字内容

ViewActions.click()

点击

ViewActions.scrollTo()

滑动

ViewActions.pressKey()

按下按键

ViewActions.clearText():

清空文本

另外,在最上面的例子中的“closeSoftKeyboard()”表示输入字符以后收起键盘。

4、断言

一般断言如下所示。

onView(withId(R.id.tv1)).check(matches(withText(expectedText)));

方法check()表示检查, matches()表示匹配,matches()方法中的参数同定位。同matches()方法一样经常使用的,还有。

doesNotExist()

断言某一个view不存在

matches()

断言某个view存在,且符合一列的匹配

selectedDescendentsMatch()

断言指定的子元素存在,且他们的状态符合一些列的匹配

代码

onView(withText(startsWith("用户名或密码"))) .inRoot(withDecorView(not(mActivityRule.getActivity().getWindow().getDecorView()))) .check(matches(isDisplayed()));

是一个检查Toast很有用的方法,这个如果你使用UiAutomation是很难实现的。

星云测试

http://www.teststars.cc

奇林软件

http://www.kylinpet.com

联合通测

http://www.quicktesting.net

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 软件测试培训 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
CODING DevOps
CODING DevOps 一站式研发管理平台,包括代码托管、项目管理、测试管理、持续集成、制品库等多款产品和服务,涵盖软件开发从构想到交付的一切所需,使研发团队在云端高效协同,实践敏捷开发与 DevOps,提升软件交付质量与速度。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档