Espressoとは
- googleが開発を行っている。
- AndroidのUIテストフレームワーク
- 自動同期(Automatic Synchronization)
- 基本的な操作が簡単にかける(テキスト入力、クリック、スクロール、スワイプ)
- 自分が欲しいアクションが提供されていない場合は自分で作ることも可能
導入
gradleに以下のコードを追加
最新のバージョンは公式サイトを参照してください。
dependencies {
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
}
新規登録画面のフローテスト
idとパスワードを入力し、ボタンを押すと次の画面へ遷移するアプリを考えます。
この時、登録に失敗した場合には上の方にエラーメッセージを表示します。
SignUp失敗時のテスト
@Test
public void checkErrorMessage() {
onView(withId(R.id.user_id)).perform(replaceText(""));
onView(withId(R.id.password)).perform(replaceText(password), closeSoftKeyboard());
onView(withId(R.id.signup_button)).perform(click());
onView(withId(R.id.error_message)).check(matches(withText("ユーザーIDを入力してください。")));
}
SignUp成功時のテスト
@Test
public void checkSignUp() {
onView(withId(R.id.user_id)).perform(replaceText(userId));
onView(withId(R.id.password)).perform(replaceText(password), closeSoftKeyboard());
onView(withId(R.id.signup_button)).perform(click());
onView(withId(R.id.hello_world)).check(matches(withText("Hello World, " + userId + "!!")));
}
CustomMatcher
先ほどの上のwithTextでは画面上のテキストの値をチェックしていましたが、自分でカスタマイズしたMatcherも作ることができます。
例えばTextViewの色をチェックするCustomMatcherを実装するにはmatchesSafelyメソッドとdescribeToメソッドをオーバーライドします。
matchesSafelyで独自のMatcherを定義し、describeToでログの表示を定義します。
private static Matcher<Object> withColor(final Matcher<Integer> integerMatcher) {
return new BoundedMatcher<Object, TextView>(TextView.class) {
@Override
public boolean matchesSafely(TextView textView) {
return integerMatcher.matches(textView.getCurrentTextColor());
}
@Override
public void describeTo(Description description) {
description.appendText("with resource color : ");
integerMatcher.describeTo(description);
}
};
}
onView(withId(R.id.error_message))
.check(matches(withColor(is(ContextCompat.getColor(activity, android.R.color.holo_red_light)))));
Idling Resource
ある条件を満たした後にアクションを行う。
アニメーションが終了した後にスクロールを開始する。5秒たった後にボタンを押下する。など。
これは、IdlingResourceをimplementsしたクラスで実装します。
以下はhoge秒後にアクションを行う処理を行う場合
public class ElapsedTimeIdlingResource implements IdlingResource {
private final long startTime;
private final long waitingTime;
private IdlingResource.ResourceCallback resourceCallback;
public ElapsedTimeIdlingResource(long waitingTime) {
this.startTime = System.currentTimeMillis();
this.waitingTime = waitingTime;
}
@Override
public String getName() {
return ElapsedTimeIdlingResource.class.getName() + ":" + waitingTime;
}
@Override
public boolean isIdleNow() {
long elapsed = System.currentTimeMillis() - startTime;
boolean idle = (elapsed >= waitingTime);
if (idle) {
resourceCallback.onTransitionToIdle();
}
return idle;
}
@Override
public void registerIdleTransitionCallback(IdlingResource.ResourceCallback resourceCallback) {
this.resourceCallback = resourceCallback;
}
}
@Test
public void checkErrorMessage() {
// Now we wait 8 seconds for some reason
IdlingResource idlingResource = new ElapsedTimeIdlingResource(DateUtils.SECOND_IN_MILLIS * 8);
Espresso.registerIdlingResources(idlingResource);
onView(withId(R.id.error_message)).check(matches(withColor(is(ContextCompat.getColor(activity, android.R.color.holo_red_light)))));
// Clean up
Espresso.unregisterIdlingResources(idlingResource);
}
考察
Espressoの文法は見た目がわかりやすく、コード量も少なくて済むのですごく良いです。
この記事のコードはGitHub上にEspressoDemoという名前で公開しているので、ぜひ。
話は逸れますが、個人的にAndroidアプリMapMeとNetflixの映画レビューサイトWhatchaSeeを運営しています。
拝見していただけるとありがたいです。