前言
最近这两周工作相对不那么忙了,所以就抽空结合官方文档研究了一下Android UI测试框架Espresso,从框架的setup到测试用例编写到执行测试用例
简介
Espresso是Google官方推出的开源UI测试框架,它的特点就是简洁,很容易上手编写测试用例,而且关于UI测试Espresso支持的也越来越完善了
官方项目地址:点击查看Espresso测试框架详细信息
安装
在dependencies里面添加引用1
2
3
4
5
6
7
8// App dependencies
compile 'com.android.support:support-annotations:23.0.1'
// Testing-only dependencies
// Force usage of support annotations in the test app, since it is internally used by the runner module.
androidTestCompile 'com.android.support:support-annotations:23.0.1'
androidTestCompile 'com.android.support.test:runner:0.4.1'
androidTestCompile 'com.android.support.test:rules:0.4.1'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
在android.defaultConfig
设置instrumentation runner
1
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
这里有一点需要注意的是官方文档中添加依赖的样例是这样的1
2
3
4
5
6
7
8dependencies {
// App\'s dependencies, including test
compile 'com.android.support:support-annotations:22.2.0'
// Testing-only dependencies
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
}
如果按照官方的这个来,build的时候你会遇到这样一个错误:1
Error:Conflict with dependency 'com.android.support:support-annotations'
详情如下图所示:
产生这种错误的原因如下:
通常是因为你的主程序和测试程序使用了相同的库,但是使用的版本却不一样,你可能会觉得奇怪,看代码里面测试依赖并没有引用support-annotations
库啊,为什么会说测试程序和主程序使用了相同的库,这是因为在测试库runner
中内部使用了support-annotations
库,而且我们知道在运行的时候主程序apk和测试apk是共享同一个进程和相同的class path,这就代表主程序和测试程序必须使用相同版本的任何依赖库,一旦版本不同,所以才会出现上面的冲突错误形象说明见下图:
解决办法:
既然知道了问题产生的原因,那么解决办法也很简单,两种方法:
- 更改主程序里面对应冲突库的版本使其于测试程序里面的版本一致
- 更改测试程序里面冲突库的版本使其于主程序中的版本一致
通常比较简单的做法就是在build.gradle文件中显式加入另一个test dependencies和主程序代码中的冲突库版本一致的库,这样就强制要求测试程序也使用和主程序相同版本的库文件,像这样:1
2
3
4
5
6
7
8dependencies {
// App\'s dependencies, including test
compile '...:support-annotations:23.3.0'
// Testing-only dependencies
// Force the same version of support-annotations
compile '...:support-annotations:23.3.0'
}
编写测试用例
这个很简单,只要结合官方文档给出的例子,看看文档说明和对应的API,很容易上手,下面是我写的一个打开NavigationView的测试用例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void openNavigationView() {
onView(withId(R.id.drawer_layout)).perform(
actionOpenNavigationView());
}
private ViewAction actionOpenDrawer() {
return new ViewAction() {
public Matcher<View> getConstraints() {
return isAssignableFrom(DrawerLayout.class);
}
public String getDescription() {
return "open drawer";
}
public void perform(UiController uiController, View view) {
((DrawerLayout) view).openDrawer(GravityCompat.START);
}
};
}
解释几个关键类:
Espresso
和视图views的交互切入点(通过onView和onData),而且也会暴露不需要依赖任何view的API(eg.pressBack)
ViewMatchers
这个是我们如何find views的方式. ViewMatchers包含一个允许你在视图层次结构中找到指定的view的matchers的集合.以上,我们使用withId(R.id.etInput)来指明我们正在寻找的一个EditText,通过id = R.id.etInput
ViewActions
这是我们如何和views交互,我们使用typeText(…)方法来在EditText写入hello
##ViewAssertions
这是我们的验证类. 我们使用ViewAssertions来验证views的指定属性. 大部分时候你将会使用由ViewMatchers下驱动的ViewAssertions. 在我们上面的例子中withText(…)方法实际上返回一个我们已经使用matchs(…)方法转换成一个ViewAssertion的ViewMatcher
Espresso测试的标准模式是find a view(ViewMatchers), 在view上做一些事情(ViewActions), 然后验证view的一些属性(ViewAssertions).
例子:1
2
3onView(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
附上一张官网帮助记忆的小抄:
执行
执行测试用例有两种方法:
- 直接像运行app一样,通过Android Studio选择执行对应的测试程序
- 在项目根目录执行:./gradlew :testPreject:connectedAndroidTest
参考
1.https://google.github.io/android-testing-support-library/
2.https://guides.codepath.com/android/UI-Testing-with-Espresso
3.https://www.youtube.com/watch?v=OOEDKf06WqA