Android鬼点子-使用Espresso进行UI测试


       Android鬼点子系列第二篇,使用Espresso进行UI测试。这是一篇入门级别的教程。Espresso是谷歌官方的一个测试框架。 在Android Studio2.2中直接创建app类型的module,默认就会使用这个框架。

       Espresso的代码在包名下androidTest,(多说一句,这里还有一个叫做test的包,这个包下面是进行Junit测试)。说一说这两种测试的不同,Junit的更偏向于测试逻辑,不运行在模拟器中;Espresso是测试UI,比如点击按钮后TextView显示的内容是否正确。Espresso是运行在模拟器中的。

Espresso测试是非常容易实现的,它由三部分组成: 
    ViewMachers:寻找用来测试的View。 
    ViewActions:发送交互事件。 
    ViewAssertions:检验测试结果。

       在包名下androidTest,默认创建ExampleInstrumentedTest.java。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.example.test;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static junit.framework.Assert.assertEquals;
/**
* Instrumentation test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.example.test", appContext.getPackageName());
}
}

       我们发现这里使用了assertEquals断言,所以Espresso是建立在Junit基础上的。在gradle配置如下:

1
2
3
4
5
6
7
8
9
10
11
repositories {
mavenCentral()
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:23.4.0'
testCompile 'junit:junit:4.12'
}

基本的使用方法:
onView(ViewMatcher).perform(ViewAction).check(ViewAssertion);

下面的方法适用于使用Adapter的View。
onData(ObjectMatcher).DataOptions.perform(ViewAction).check(ViewAssertion);

1、寻找测试元素(Matcher)

       Espresso提供了一个onView()方法用来寻找UI上指定的元素.onView的输入参数是一个Matcher对象,有很多方法都会返回这个对象,我们可以把这些方法理解为寻找测试View的规则。

withId()使用控件的ID进行查找
withText()使用控件上的Text属性的值进行查找
还有withHint(),withTagKey()等等

2、进行操作(ViewAction)

       比如点击,双击,长按等等,当然这个步奏不是必须的。perform()里面可以传进驱若干个参数,也就是若干个动作,这些动作会依次执行。

1
2
onView(withId(id)).perform(click(), clearText(), closeSoftKeyboard())

3、检测结果(ViewAssertion)

       最后查看结果,例如:matches(Matcher),isAbove(Matcher)等等。

1
2
onView(withText("Hello world!")).check(matches(isDisplayed()));

       附上一个网上别人写的例子地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@RunWith(AndroidJUnit4.class)
public class LoginActivityTest{
@Rule
//注解定义规则
public ActivityTestRule<LoginActivity> mActivityRule = new ActivityTestRule<>(
LoginActivity.class);
@Test
//测试用例
public void test(){
//清除 之前输入点用户名和密码
onView(withId(R.id.login_et_username)).perform(clearText());
onView(withId(R.id.login_et_password)).perform(clearText());
//输入用户名和密码并关闭软键盘
onView(withId(R.id.login_et_username)).perform(typeText("18500000000\n"), closeSoftKeyboard());
onView(withId(R.id.login_et_password)).perform(typeText("wjf"),closeSoftKeyboard());
//触发登录按钮的点击事件
onView(withId(R.id.login_fa_login)).perform(click());
//通过断言判断是否登录成功,这里通过会话列表是否显示来判断
onView(withId(R.id.list_fl_list)).check(ViewAssertions.matches(isDisplayed()));
}
}

       当你的View是使用Adapter的时候,可能显示在画面上的并不是整个View,实际上并没有加载整个View。这里就要使用onData()了。

1
2
3
4
5
6
7
8
9
//如果使用的是 SimpleAdapter,那么data的类型就Map型,如下:
Map:{"STR" : "item: 50", "LEN": 7}
//模拟一个点击显示内容是"item: 50"的item。
onData(allOf(is(instanceOf(Map.class)), hasEntry(equalTo("STR"), is("item: 50")))
.perform(click());
onData(withItemContent("item: 60"))
.onChildView(withId(R.id.item_size))
.perform(click());

       edittext 中 搜狗输入法输入的 内容,在自动化之行过程中,可能出现输入不全的问题,可换用系统自带输入法,或者谷歌原生输入法。
当有多个edittext 时候,可能出现第一个edittext 输入完之后,第二个输入无反应,可以在typeText()中的字符后面加上 “\n” 尝试解决。 谷歌官方文档

最后一张图可以总结我上面的废话:
espresso-cheat-sheet-2.1.0

文章目录
|