Android
Espresso
testing

EspressoテストでTextInputLayoutのエラーを確認したい

More than 3 years have passed since last update.


TextInputLayoutのエラー表示を確認する

EditText用のエラーテキスト内容を確認するMatcherは存在するが、InputTextLayout用がなかったので

カスタムMatcherをwithTextのMatcherを参考に作成した

エラーかどうか、エラーのテキストを文字列、または文字列リソースでマッチングできるようにしている

    public static Matcher<View> withErrorText(String text) {

return withErrorText(is(text));
}

public static Matcher<View> withErrorText(final Matcher<String> stringMatcher) {
return new BoundedMatcher<View, TextInputLayout>(TextInputLayout.class) {
@Override
public void describeTo(Description description) {
description.appendText("with Error Text: ");
stringMatcher.describeTo(description);
}

@Override
public boolean matchesSafely(TextInputLayout textInputLayout) {
CharSequence error = textInputLayout.getError();
return error != null && stringMatcher.matches(error.toString());
}
};
}

public static Matcher<View> withErrorText(final int resourceId) {
return new BoundedMatcher<View, TextInputLayout>(TextInputLayout.class) {
private String resourceName = null;
private String expectedText = null;

@Override
public void describeTo(Description description) {
description.appendText("with string from resource id: ");
description.appendValue(resourceId);
if (null != resourceName) {
description.appendText("[");
description.appendText(resourceName);
description.appendText("]");
}
if (null != expectedText) {
description.appendText(" value: ");
description.appendText(expectedText);
}
}

@Override
public boolean matchesSafely(TextInputLayout textInputLayout) {
if (null == expectedText) {
try {
expectedText = textInputLayout.getResources().getString(resourceId);
resourceName = textInputLayout.getResources().getResourceEntryName(resourceId);
} catch (Resources.NotFoundException ignored) {
// NOP
}
}
CharSequence actualText = null;

actualText = textInputLayout.getError();

if (null != expectedText && null != actualText) {
// FYI: actualText may not be string ... its just a char sequence convert to string.
return expectedText.equals(actualText.toString());
} else {
return false;
}
}
};
}

public static Matcher<View> hasError() {
return new BoundedMatcher<View, TextInputLayout>(TextInputLayout.class) {
@Override
public void describeTo(Description description) {
description.appendText("has Error");
}

@Override
public boolean matchesSafely(TextInputLayout textInputLayout) {
CharSequence error = textInputLayout.getError();
return error != null;
}
};
}


使用例

ログイン画面で同じ内容のエラー文言が並ぶ場合などで効果を発揮する

allOf(withId(),withText())でも確認できるが、カスタムmatcherの方がスッキリすると思った

    public void エラーテスト() {

onView(withId(R.id.textInputLayout_mail)).check(matches(isDisplayed()));
onView(withId(R.id.textInputLayout_mail)).check(matches(hasError()));
onView(withId(R.id.textInputLayout_mail)).check(matches(withErrorText("入力してください")));
onView(withId(R.id.textInputLayout_mail)).check(matches(withErrorText(R.string.error_message_required)));
onView(withId(R.id.textInputLayout_password)).check(matches(not(hasError())));
}

参考:

https://developer.android.com/reference/android/support/test/espresso/matcher/ViewMatchers.html?hl=ja