Espresso - Как проверить отображение одного из видов
В моем тесте, после одного действия, есть два возможных вида, которые могут появиться, и оба они верны. Как проверить, отображается ли одно из представлений. Для одного вида, с которым я могу проверить, отображается Displayed(). Но это не сработает, если вместо этого будет видно другое представление. Я хочу пройти тест, если будет отображаться любое из этих двух представлений.
onMyButton.perform(click());
onMyPageOne.check(matches(isDisplayed())); //view 1
or
onMyPageTwo.check(matches(isDisplayed())); //view 2
После этого нажмите "MyButton", ожидается, что появится какое-либо из представлений (1 или 2), но не оба. Не фиксировано, какой из них будет отображаться.
Как проверить, отображен ли какой-либо из них?
Ответы
Ответ 1
Можно поймать исключения, вызванные Espresso, как это:
Если вы хотите проверить, находится ли представление в иерархии:
try {
onView(withText("Button")).perform(click());
// View is in hierarchy
} catch (NoMatchingViewException e) {
// View is not in hierarchy
}
Это исключение будет вызываться, если представление в иерархии не.
Иногда представление может быть в иерархии, но нам нужно проверить, отображается ли оно, поэтому для утверждений есть другое исключение:
try {
onView(withText("Button")).check(matches(isDisplayed()));
// View is displayed
} catch (AssertionFailedError e) {
// View not displayed
}
Ответ 2
Здесь есть два случая, которые вы могли бы попытаться охватить. Во-первых, если вы проверяете, отображается ли на экране изображение "на экране", в этом случае вы использовали бы isDisplayed()
onView(matcher).check(matches(isDisplayed()));
или отрицание
onView(matcher).check(matches(not(isDisplayed())));
В другом случае вы проверяете, видимо ли это вид, но не обязательно отображается на экране (т.е. элемент в прокрутке). Для этого вы можете использовать withEffectiveVisibility(Visibility)
onView(matcher).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)));
Ответ 3
Вы можете использовать Matchers.anyOf, чтобы проверить, отображается ли какое-либо из двух видов:
onView(
anyOf(withId(R.id.view_1), withId(R.id.view_2))
).check(matches(isDisplayed()));
Ответ 4
Я немного исследовал эспрессо и нашел это @Espresso Samples.
-
Поиск текста "Утверждение, что представление не отображается". Он говорит: "Приведенный выше подход работает, если представление все еще является частью иерархии". Поэтому я думаю, что ваш код должен работать, но вам также нужно использовать ViewAssertions
. Используя ваш код, возможно, сделайте это:
if (ViewAssertions.doesNotExist()) == null) {
return;
}
onMyPageOne.check(matches(isDisplayed()));
-
Другой метод - проверка существования пользовательского интерфейса. Поиск текста "Утверждение, что представление отсутствует". Используя ваш код, мое лучшее предложение:
onMyPageOne.check(doesNotExist());
Примечание. Этот метод вызывает метод doesNotExist
.
Их пример кода: onView(withId(R.id.bottom_left)).check(doesNotExist());
Ответ 5
Для тех, кто хочет проверить статус видимости для вида; Вот некоторые полезные функции, которые я использую.
fun ViewInteraction.isGone() = getViewAssertion(ViewMatchers.Visibility.GONE)
fun ViewInteraction.isVisible() = getViewAssertion(ViewMatchers.Visibility.VISIBLE)
fun ViewInteraction.isInvisible() = getViewAssertion(ViewMatchers.Visibility.INVISIBLE)
private fun getViewAssertion(visibility: ViewMatchers.Visibility): ViewAssertion? {
return ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(visibility))
}
И можно использовать следующим образом
onView(withId(R.id.progressBar)).isVisible()
onView(withId(R.id.progressBar)).isGone()
Ответ 6
Класс утилит, который позволяет проверить, является ли представление visible
, gone
или invisible
:
public class ExtraAssertions {
public static ViewAssertion isVisible() {
return new ViewAssertion() {
public void check(View view, NoMatchingViewException noView) {
assertThat(view, new VisibilityMatcher(View.VISIBLE));
}
};
}
public static ViewAssertion isGone() {
return new ViewAssertion() {
public void check(View view, NoMatchingViewException noView) {
assertThat(view, new VisibilityMatcher(View.GONE));
}
};
}
public static ViewAssertion isInvisible() {
return new ViewAssertion() {
public void check(View view, NoMatchingViewException noView) {
assertThat(view, new VisibilityMatcher(View.INVISIBLE));
}
};
}
private static class VisibilityMatcher extends BaseMatcher<View> {
private int visibility;
public VisibilityMatcher(int visibility) {
this.visibility = visibility;
}
@Override public void describeTo(Description description) {
String visibilityName;
if (visibility == View.GONE) visibilityName = "GONE";
else if (visibility == View.VISIBLE) visibilityName = "VISIBLE";
else visibilityName = "INVISIBLE";
description.appendText("View visibility must has equals " + visibilityName);
}
@Override public boolean matches(Object o) {
if (o == null) {
if (visibility == View.GONE || visibility == View.INVISIBLE) return true;
else if (visibility == View.VISIBLE) return false;
}
if (!(o instanceof View))
throw new IllegalArgumentException("Object must be instance of View. Object is instance of " + o);
return ((View) o).getVisibility() == visibility;
}
}
}
И использование может выглядеть так:
onView(withId(R.id.text_message)).check(isVisible());
Другое утверждение представления, которое может помочь проверить дополнительные свойства видимости представления и его родителей: оно проверяет visibility
, isAttachedToWindow
, alpha
:
class IsVisible : ViewAssertion {
override fun check(view: View, noViewFoundException: NoMatchingViewException?) {
ViewMatchers.assertThat(
"View is not visible. " +
"visibility: ${view.visibility}, " +
"isAttachedToWindow: ${view.isAttachedToWindow}, " +
"alpha: ${view.alpha}",
true, 'is'(isViewTreeVisible(view)))
}
private fun isViewTreeVisible(view: View?): Boolean {
return if (view != null) {
val viewVisible = view.isAttachedToWindow && view.visibility == View.VISIBLE && view.alpha == 1.0f
if (view.parent !is View) viewVisible
else viewVisible && isViewTreeVisible(view.parent as View)
} else {
true
}
}
}
Ответ 7
Проблема заключается в том, что все методы assertoin()
и check()
возвращают Assertion
, которые останавливают тестовый поток, если не удалось.
Ответ 8
Один простой способ проверить вид или его подкласс, как Button, - использовать метод
getVisibility из класса Вид. Я должен предупредить, что атрибут видимости четко не определен в мире GUI. Вид может считаться видимым, но может быть перекрыт другим видом, например, скрыть его.
Другой способ, но более точный (я не пробовал) - проверить прямоугольные границы представления. Не так просто.
Является ли это достаточно ясным? не может дать вам конкретные примеры, поскольку вы не отправляли код.
Ответ 9
final AtomicBoolean view1Displayed = new AtomicBoolean(true);
Espresso.onView(ViewMatchers.withId(viewId1)).inRoot(RootMatchers.withDecorView(Matchers.is(intentsTestRule.getActivity().getWindow().getDecorView()))).withFailureHandler(new FailureHandler() {
@Override
public void handle(Throwable error, Matcher<View> viewMatcher) {
view1Displayed.set(false);
}
}).check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
if (view1Displayed.get()) {
try {
Espresso.onView(ViewMatchers.withId(viewId2)).inRoot(RootMatchers.withDecorView(Matchers.is(intentsTestRule.getActivity().getWindow().getDecorView()))).check(ViewAssertions.matches(Matchers.not(ViewMatchers.isDisplayed())));
} catch (NoMatchingViewException ignore) {
}
} else {
Espresso.onView(ViewMatchers.withId(viewId2)).inRoot(RootMatchers.withDecorView(Matchers.is(intentsTestRule.getActivity().getWindow().getDecorView()))).check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
}
Ответ 10
Прошло некоторое время с тех пор, как эта проблема была заявлена, но, поскольку она является одной из самых популярных в Google при поиске способов убедиться, что представление присутствует, перед выполнением каких-либо действий с ним в Espresso я хотел бы поделиться своими основными способ справиться с этим.
1: я начал с написания расширения для ViewInteraction
:
fun ViewInteraction.exists(): Boolean {
val viewExists = AtomicReference<Boolean>()
this.perform(object : ViewAction {
override fun perform(uiController: UiController?, view: View?) {
viewExists.set(view != null)
}
override fun getConstraints(): Matcher<View>? {
return Matchers.allOf(ViewMatchers.withEffectiveVisibility(
ViewMatchers.Visibility.VISIBLE),
ViewMatchers.isAssignableFrom(View::class.java))
}
override fun getDescription(): String {
return "check if view exists"
}
})
return viewExists.get()
}
2: Затем я создал простой метод справки в своем базовом классе (который будет использоваться во всех моих тестовых классах):
fun viewExists(id: Int): Boolean {
return try {
onView(withId(id)).exists()
} catch (e: PerformException) {
false
}
}
При этом я либо получаю true
или false
из onView(withId(id)).exists()
, либо я благополучно перехватываю PerformException и возвращаю false
.
Обычно достаточно простой проверки для .exists()
, в моем случае, однако, я удаляю элементы ListView до тех пор, пока не останется non - и когда мой последний элемент будет удален, мой ListView больше не будет присутствовать, поэтому я получу PerformException
когда пытаясь проверить, существует ли он.
3: С вышеупомянутой реализацией я могу безопасно проверить, существует ли какое-либо представление следующим образом, так как PerformException
хорошо обрабатывается за сценой:
if(viewExists(R.id.something)) {
//do something
}
//do something else