webentwicklung-frage-antwort-db.com.de

Espresso - So prüfen Sie, ob eine der Ansichten angezeigt wird

In meinem Test gibt es nach einer Aktion zwei mögliche Ansichten, die angezeigt werden können, und beide sind korrekt. Wie kann ich überprüfen, ob eine Ansicht angezeigt wird? Für eine einzelne Ansicht kann ich überprüfen, ob sie angezeigt wird (). Dies würde jedoch fehlschlagen, wenn stattdessen eine andere Ansicht sichtbar ist. Ich möchte den Test bestehen, wenn eine der beiden Ansichten angezeigt wird.

onMyButton.perform(click());

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

Nachdem Sie auf MyButton geklickt haben, wird erwartet, dass eine der Ansichten (1 oder 2) erscheint, nicht jedoch beide. Es ist nicht festgelegt, welche angezeigt werden würde. Wie kann ich überprüfen, ob einer von ihnen angezeigt wird?

39
user846316

Es ist möglich, die von Espresso hervorgerufenen Ausnahmen wie folgt zu erfassen:

Wenn Sie testen möchten, ob eine Ansicht in der Hierarchie ist:

try {
    onView(withText("Button")).perform(click());
    // View is in hierarchy

} catch (NoMatchingViewException e) {
    // View is not in hierarchy
}

Diese Ausnahme wird ausgelöst, wenn die Ansicht nicht in der Hierarchie ist.

Manchmal kann sich die Ansicht in der Hierarchie befinden, aber wir müssen testen, ob sie angezeigt wird. Daher gibt es eine weitere Ausnahme für Assertions:

try {
    onView(withText("Button")).check(matches(isDisplayed()));
    // View is displayed
} catch (AssertionFailedError e) {
    // View not displayed
}
43
Lafayette

Es gibt zwei Fälle, in denen Sie versuchen könnten, zu behandeln. Der erste ist, wenn Sie prüfen, ob dem Benutzer die Ansicht "auf dem Bildschirm angezeigt wird" In diesem Fall würden Sie isDisplayed() verwenden.

onView(matcher).check(matches(isDisplayed()));

oder die Verneinung

onView(matcher).check(matches(not(isDisplayed())));

Der andere Fall ist, wenn Sie prüfen, ob die Ansicht sichtbar ist, aber nicht unbedingt auf dem Bildschirm angezeigt wird (z. B. ein Element in einer Bildlaufansicht). Hierfür können Sie withEffectiveVisibility(Visibility) verwenden.

onView(matcher).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)));
28
RyPope

Sie können Matchers.anyOf verwenden, um zu prüfen, ob eine der beiden Ansichten angezeigt wird:

onView(
   anyOf(withId(R.id.view_1), withId(R.id.view_2)) 
).check(matches(isDisplayed()));
19
Luiz Augusto

Ich habe nach Espresso recherchiert und diese @ Espresso Samples gefunden. 

  1. Suchtext "Feststellen, dass eine Ansicht nicht angezeigt wird". Es heißt "Der obige Ansatz funktioniert, wenn die Ansicht noch Teil der Hierarchie ist." Ich denke, Ihr Code sollte funktionieren, aber Sie müssen auch ViewAssertions verwenden. Vielleicht verwenden Sie Ihren Code:

    if (ViewAssertions.doesNotExist()) == null) {
       return;
    }
    onMyPageOne.check(matches(isDisplayed()));
    
  2. Eine andere Technik ist die Überprüfung der Existenz der Benutzeroberfläche. Suchen Sie nach dem Text "Feststellen, dass keine Ansicht vorhanden ist" . Wenn Sie Ihren Code verwenden, ist mein bester Vorschlag:

    onMyPageOne.check (doesNotExist ());

Hinweis: Dies ruft die doesNotExist-Methode auf.

Ihr Beispielcode lautet: onView(withId(R.id.bottom_left)).check(doesNotExist());

Dienstprogrammklasse, mit der überprüft werden kann, ob die Ansicht visible, gone oder invisible ist:

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;
        }
    }
}

Und die Nutzung könnte so aussehen:

onView(withId(R.id.text_message)).check(isVisible());

Eine weitere Ansichtsannahme, die helfen kann, zusätzliche Sichtbarkeitseigenschaften einer Ansicht und ihrer übergeordneten Elemente zu überprüfen: 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
        }
    }
}
6
eleven

Das Problem ist, dass alle assertoin()- und check()-Methoden Assertion zurückgeben.

3
Dmitry Gr

Für diejenigen, die den Sichtbarkeitsstatus für eine Ansicht überprüfen möchten; Hier sind einige Funktionen, die ich verwende.

fun isGone() = getViewAssertion(ViewMatchers.Visibility.GONE)

fun isVisible() = getViewAssertion(ViewMatchers.Visibility.VISIBLE)

fun isInvisible() = getViewAssertion(ViewMatchers.Visibility.INVISIBLE)

private fun getViewAssertion(visibility: ViewMatchers.Visibility): ViewAssertion? {
    return ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(visibility))
}

Und kann wie folgt verwendet werden

onView(withId(R.id.progressBar)).check(isVisible())
onView(withId(R.id.progressBar)).check(isGone())
2
dgngulcan

Eine einfache Möglichkeit, nach einer Ansicht oder ihrer Unterklasse wie einem Button zu suchen, ist die Methode getVisibility from View class. Ich muss darauf hinweisen, dass das Sichtbarkeitsattribut in der GUI-Welt nicht klar definiert ist. Eine Ansicht kann als sichtbar betrachtet werden, kann aber beispielsweise mit einer anderen Ansicht überlappt werden, sodass sie ausgeblendet wird.

Ein anderer Weg, aber genauer (ich habe es nicht versucht) ist, die rechteckigen Grenzen der Ansicht zu überprüfen. Nicht so einfach.

Ist das klar genug? Ich kann Ihnen keine spezifischen Beispiele geben, da Sie keinen Code eingegeben haben.

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()));
    }
0
Dipesh Rathod