上周和大家分享了《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官網
歡迎關注我的微博