Dans mon test, après une action, il y a deux vues possibles qui peuvent apparaître et les deux sont correctes. Comment puis-je vérifier si l'une des vues est affichée? Pour une vue unique, je peux vérifier avec est Affiché (). Mais cela échouerait si une autre vue était visible à la place. Je souhaite réussir le test si l'une de ces deux vues est affichée.
onMyButton.perform(click());
onMyPageOne.check(matches(isDisplayed())); //view 1
or
onMyPageTwo.check(matches(isDisplayed())); //view 2
Après, cliquez sur MyButton, l’une des vues (1 ou 2) devrait apparaître, mais pas les deux. Il n'est pas fixé ce que l'un serait affiché. Comment puis-je vérifier si l'un d'entre eux est affiché?
Il est possible d'attraper les exceptions soulevées par Espresso comme ceci:
Si vous voulez tester si une vue est dans la hiérarchie:
try {
onView(withText("Button")).perform(click());
// View is in hierarchy
} catch (NoMatchingViewException e) {
// View is not in hierarchy
}
Cette exception sera levée si la vue est pas dans la hiérarchie.
Parfois, la vue peut être dans la hiérarchie, mais nous devons vérifier si elle est affichée. Il existe donc une autre exception pour les assertions, comme celle-ci:
try {
onView(withText("Button")).check(matches(isDisplayed()));
// View is displayed
} catch (AssertionFailedError e) {
// View not displayed
}
Vous pourriez essayer de couvrir deux cas. La première est si vous vérifiez si la vue "est affichée à l'écran pour l'utilisateur" auquel cas vous utiliseriez isDisplayed()
onView(matcher).check(matches(isDisplayed()));
ou la négation
onView(matcher).check(matches(not(isDisplayed())));
L'autre cas est si vous vérifiez si la vue est visible mais pas nécessairement affichée à l'écran (c'est-à-dire un élément dans une vue à défilement). Pour cela, vous pouvez utiliser withEffectiveVisibility(Visibility)
onView(matcher).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)));
Vous pouvez utiliser Matchers.anyOf pour vérifier si l’une des deux vues est affichée:
onView(
anyOf(withId(R.id.view_1), withId(R.id.view_2))
).check(matches(isDisplayed()));
J'ai un peu cherché l’Espresso et j’ai trouvé ceci @ Exemples d’Espresso .
Texte de recherche "En affirmant qu'une vue n'est pas affichée". "L'approche ci-dessus fonctionne si la vue fait toujours partie de la hiérarchie". Je pense donc que votre code devrait fonctionner, mais vous devez également utiliser ViewAssertions
. En utilisant votre code, faites peut-être ceci:
if (ViewAssertions.doesNotExist()) == null) {
return;
}
onMyPageOne.check(matches(isDisplayed()));
Une autre technique consiste à vérifier l'existence d'une interface utilisateur. Recherchez le texte "Affirmer qu’une vue n’est pas présente" . À l’aide de votre code, ma meilleure suggestion est la suivante:
onMyPageOne.check (doesNotExist ());
Remarque: Ceci appelle la méthode doesNotExist
.
Leur exemple de code est: onView(withId(R.id.bottom_left)).check(doesNotExist());
Classe d'utilitaires permettant de vérifier si la vue est visible
, gone
ou 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;
}
}
}
Et l'utilisation pourrait ressembler à ceci:
onView(withId(R.id.text_message)).check(isVisible());
Une autre assertion de vue qui pourrait aider à vérifier les propriétés de visibilité supplémentaires d’une vue et de ses parents: elle vérifie 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
}
}
}
Le problème est que toutes les méthodes assertoin()
et check()
renvoient Assertion
qui arrête le flux de test en cas d'échec.
Pour ceux qui cherchent à vérifier le statut de visibilité d'une vue; voici quelques fonctions utilitaires que j'utilise.
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))
}
Et peut être utilisé comme suit
onView(withId(R.id.progressBar)).check(isVisible())
onView(withId(R.id.progressBar)).check(isGone())
Un moyen simple de rechercher une vue ou sa sous-classe comme un bouton consiste à utiliser la méthode getVisibility from View class. Je dois mettre en garde que l'attribut de visibilité n'est pas clairement défini dans le monde de l'interface graphique. Une vue peut être considérée comme visible mais peut se chevaucher avec une autre vue, par exemple en la masquant.
Une autre façon, mais plus précise (je n'ai pas essayé), est de vérifier les limites rectangulaires de la vue. Pas si simple.
Est-ce assez clair? Je ne peux pas vous donner d’exemples précis puisque vous n’avez pas posté de code.
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()));
}