Espresso は以下の非同期処理は考慮してくれるようですが.
- メッセージキューを利用したUIイベント
- デフォルト AsyncTask のスレッドプールを利用したタスク
Square Island: Espresso: Custom Idling Resource
これらに該当しない処理でも, テスト実行を「あるタイミング」まで待たせたいときがありますよね?
カスタムした「IdlingResource」を使ってみましょう.
Espresso Idling Resource
ここで書かれているアプローチとしては2つ.
Counting running jobs: When a job starts, increment a counter. When it finishes, decrement it. The app is idle if the counter is zero. This approach is very simple and accounts for most situations. CountingIdlingResource does exactly this.
Querying state: It might be more reliable to ask a work queue or an HTTP client (or whatever is doing the background work) if it is busy. If the state is exposed, implementing an Idling Resource is trivial.
これらのうち, 汎用的に使えるジョブカウンターを利用した方法を, Googleサンプルを眺めつつ手順整理しておきます.
Android Testing Codelab
1. IdlingResource ユーティリティの作成
アイドリング向けのユーテリティを作成します.
そのまま2つのクラスを利用してもいいかもしれません.
EspressoIdlingResource.java at master · googlecodelabs/android-testing
SimpleCountingIdlingResource.java at master · googlecodelabs/android-testing
2. テスト対象の Activity に記述
テスト対象となる Activity にテスト時に利用するメソッドを記述しておきます.
テスト時にはこのメソッドを利用して, 先ほどのユーティリティを利用登録します.
@VisibleForTesting
public IdlingResource getCountingIdlingResource() {
return EspressoIdlingResource.getIdlingResource();
}
AddNoteActivity.java at master · googlecodelabs/android-testing
NotesActivity.java at master · googlecodelabs/android-testing
3. 「待たせる」処理の記述
Presenter や View などのテスト対象クラス内にアイドリングの利用タイミングを記述しておきます.
EspressoIdlingResource.increment();
EspressoIdlingResource.decrement();
カウンターを増減しながらアイドリングを操作します.
カウンターが0になると処理が再開されます.
@Override
public void loadNotes(boolean forceUpdate) {
mNotesView.setProgressIndicator(true);
if (forceUpdate) {
mNotesRepository.refreshData();
}
// The network request might be handled in a different thread so make sure Espresso knows
// that the app is busy until the response is handled.
EspressoIdlingResource.increment(); // App is busy until further notice
mNotesRepository.getNotes(new NotesRepository.LoadNotesCallback() {
@Override
public void onNotesLoaded(List<Note> notes) {
EspressoIdlingResource.decrement(); // Set app as idle.
mNotesView.setProgressIndicator(false);
mNotesView.showNotes(notes);
}
});
}
AddNoteFragment.java at master · googlecodelabs/android-testing
NotesPresenter.java at master · googlecodelabs/android-testing
4. テスト内で登録する
テスト対象Activityに記述したメソッドを利用してテストコードへ登録します
アイドリング処理がテスト時に反映されます.
@Before
public void registerIdlingResource() {
Espresso.registerIdlingResources(
mAddNoteIntentsTestRule.getActivity().getCountingIdlingResource());
}
@After
public void unregisterIdlingResource() {
Espresso.unregisterIdlingResources(
mAddNoteIntentsTestRule.getActivity().getCountingIdlingResource());
}
AddNoteScreenTest.java at master · googlecodelabs/android-testing
まとめ
テストにかかるコストがただの自己満足で終わらないようにしたいです.
JakeWharton/okhttp-idling-resource: An Espresso IdlingResource for OkHttp.
PSA: Dont Use Espresso Idling Resources like Google does · Philosophical Hacker