上周和大家分享了《Google官方Android App架构蓝图》,内容比较简单,没想到却收到了我在简书里面最多的喜欢,非常感谢大家。后来反思了一下,可能是因为借了Google大名,而内容虽然简单却很实用,很接地气,接下来我也尽量写一些接地气的文章,还望大家多多支持。其实上次写完了《Google官方Android App架构蓝图》,觉得有很重要的东西没有写到,憋屈了一周,这个东西就是里面的单元测试和UI测试。好的架构里面最重要的一点就是易于测试,接下来就让我们来八一八Google官方Android App架构蓝图Sample里面的单元测试。本文按照todo-mvp来写。
工程结构
我们可以看到这个Sample里面有3个测试目录:androidTest,androidTestMock和test。
androidTest
测试工具:espresso和hamcrest
目的:进行UI层测试,例如点击,跳转到某个页面
例子:
@Test
public void clickAddTaskButton_opensAddTaskUi() {
// Click on the add task button
onView(withId(R.id.fab_add_task)).perform(click());
// Check if the add task screen is displayed
onView(withId(R.id.add_task_title)).check(matches(isDisplayed()));
}
androidTestMock
测试工具:espresso和hamcrest
目的:UI层测试mock数据支持
例子:
@Test
public void activeTaskDetails_DisplayedInUi() throws Exception {
loadActiveTask();
// Check that the task title and description are displayed
onView(withId(R.id.task_detail_title)).check(matches(withText(TASK_TITLE)));
onView(withId(R.id.task_detail_description)).check(matches(withText(TASK_DESCRIPTION)));
onView(withId(R.id.task_detail_complete)).check(matches(not(isChecked())));
}
private void loadActiveTask() {
startActivityWithWithStubbedTask(ACTIVE_TASK);
}
private void startActivityWithWithStubbedTask(Task task) {
// Add a task stub to the fake service api layer.
TasksRepository.destroyInstance();
FakeTasksRemoteDataSource.getInstance().addTasks(task);
// Lazily start the Activity from the ActivityTestRule this time to inject the start Intent
Intent startIntent = new Intent();
startIntent.putExtra(TaskDetailActivity.EXTRA_TASK_ID, task.getId());
mTaskDetailActivityTestRule.launchActivity(startIntent);
}
test
测试工具:mockito
目的:业务层单元测试,包括Data,Presenter等
例子:
@Test
public void saveNewTaskToRepository_showsSuccessMessageUi() {
// Get a reference to the class under test
mAddEditTaskPresenter = new AddEditTaskPresenter("1", mTasksRepository, mAddEditTaskView);
// When the presenter is asked to save a task
mAddEditTaskPresenter.createTask("New Task Title", "Some Task Description");
// Then a task is saved in the repository and the view updated
verify(mTasksRepository).saveTask(any(Task.class)); // saved to the model
verify(mAddEditTaskView).showTasksList(); // shown in the UI
}
测试工具
Espresso
Android自动化测试框架
Mockito
模拟测试框架,使我们可以在不涉及依赖关系的情况下测试代码
远程数据mock
客户端在开发过程中可能会遇到和服务端并行开发的情况,这时候就需要mock远程数据,但打包过程中就可能手动再把mock数据去除,非常麻烦,Sample里面就通过productFlavors来处理。
productFlavors {
mock {
applicationIdSuffix = ".mock"
}
prod {}
}
// Remove mockRelease as it's not needed.
android.variantFilter { variant ->
if(variant.buildType.name.equals('release')
&& variant.getFlavors().get(0).name.equals('mock')) {
variant.setIgnore(true);
}
}
我们可以看到,在开发过程中,使用mock过程下的FakeTasksRemoteDataSource,在release下会去除mock的包,只打出prod的包,这样就能避免mock的代码在release下被打入包内。
测试命令
test目录:用test命令
androidTest目录:用connectedAndroidTest命令
参考资料
todo-mvp
Mockito官网
Mockito介绍
Espresso官网
欢迎关注我的微博