Espresso适用于 Android 应用开发者使用,用来提高代码的可靠性。

Espresso是最新的 UI Test 框架, 支持 UI 的创建测试和用户流程测试, api 非常简明, 运行也非常可靠. 很适合来写白盒测试, 可以实现对代码的细节测试.

Espresso 的英文意思是浓咖啡, Let’s Go, 来喝杯 Espresso 吧!

快速开始

添加依赖库

Module/build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
android {

defaultConfig {

// Testing config
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}

dependencies {
// Testing dependencies
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'
}

新建测试类

androidTest文件夹下新建一个测试类

1
2
3
4
5
6
7
8
9
10
11
@RunWith(AndroidJUnit4.class)
public class MyTestCase {

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

@Test
public void changeText() {
onView(withId(R.id.button)).perform(click()).check(matches(withText(R.string.finish)));
}
}
  • 使用 @RunWith(AndroidJUnit4.class) 标记一个 TestCase 类
  • 使用 @Rule 标记一个测试规则
  • 使用 @Test 标记一个测试函数

运行测试类

右键测试类 -> 点击 Run 即可

1
2
3
4
5
6
7
8
Installing cn.gavinliu.testingdemo.test
DEVICE SHELL COMMAND: pm install -r "/data/local/tmp/cn.gavinliu.testingdemo.test"
pkg: /data/local/tmp/cn.gavinliu.testingdemo.test
Success


Running tests
Test running startedFinish

没有任何报错说明测试通过.

可以试着吧测试代码改成, 再次点 Run , 结果就报错了.

1
onView(withId(R.id.button)).perform(click()).check(matches(withText(R.string.app_name)));

测试不通过

Espresso 详解

Espresso 代码基本范式

1
2
onView(ViewMatcher).perform(ViewAction).check(ViewAssertion);
onData(ObjectMatcher).DataOptions.perform(ViewAction).check(ViewAssertion);
  • ViewMatcher(ObjectMatcher) : 找某些东西
  • ViewAction : 做某些事情
  • ViewAssertion : 检查某些东西

View matching

Espresso.onView() ViewMatcher 可用使用一下几种方式来指定目标 View:

  • View 的类名
  • View 的 content description
  • View 的 ID
  • View 显示的 Text

例子

点击 R.id.button 按钮, 检测文字是否为Finish
1
onView(withId(R.id.button)).perform(click()).check(matches(withText(R.string.finish)));

Adapter matching

Espresso.onData() 对于AdapterView布局 内部有很多一样的 View, 使用 View matching 就有点不太适用了, 因为onView只会载入第一个符合要求对象.

DataOptions

操作onData()返回的数据对象

  • atPosition(int) 指定某一个对象
  • onChildView(Matcher) 指定某一个子 View (循环到 View matching)
  • inAdapterView(Matcher) 指定某一个 AdapterView (循环到 Adapter matching)

例子

点击所有Text为Hello的对象
1
onData(allOf(is(instanceOf(String.class)), is("Hello"))).perform(click());

Espresso 类图关系

类图关系

基于 Espresso 的 TDD 开发实践

使用 TDD 的方式开发一个 Hacker News Android 客户端