Подтвердить что ты не робот

Espresso - Как проверить отображение одного из видов

В моем тесте, после одного действия, есть два возможных вида, которые могут появиться, и оба они верны. Как проверить, отображается ли одно из представлений. Для одного вида, с которым я могу проверить, отображается Displayed(). Но это не сработает, если вместо этого будет видно другое представление. Я хочу пройти тест, если будет отображаться любое из этих двух представлений.

onMyButton.perform(click());

onMyPageOne.check(matches(isDisplayed())); //view 1
or
onMyPageTwo.check(matches(isDisplayed())); //view 2

После этого нажмите "MyButton", ожидается, что появится какое-либо из представлений (1 или 2), но не оба. Не фиксировано, какой из них будет отображаться. Как проверить, отображен ли какой-либо из них?

4b9b3361

Ответ 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.

  1. Поиск текста "Утверждение, что представление не отображается". Он говорит: "Приведенный выше подход работает, если представление все еще является частью иерархии". Поэтому я думаю, что ваш код должен работать, но вам также нужно использовать ViewAssertions. Используя ваш код, возможно, сделайте это:

    if (ViewAssertions.doesNotExist()) == null) {
       return;
    }
    onMyPageOne.check(matches(isDisplayed()));
    
  2. Другой метод - проверка существования пользовательского интерфейса. Поиск текста "Утверждение, что представление отсутствует". Используя ваш код, мое лучшее предложение:

    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