2015-03-25 10 views
32

Nel mio test, dopo un'azione, ci sono due possibili visualizzazioni che possono apparire ed entrambe sono corrette. Come posso verificare se viene visualizzata una vista. Per una singola vista che posso verificare è visualizzato(). Ma ciò fallirebbe se invece fosse visibile un'altra vista. Voglio passare il test se viene visualizzata una di queste due visualizzazioni.Espresso - Come verificare se viene visualizzata una vista

Dopo aver eseguito fare clic su MyButton, è probabile che venga visualizzata una qualsiasi delle visualizzazioni (1 o 2), ma non entrambe. Non è fisso quello che verrebbe visualizzato. Come posso verificare se uno di questi è visualizzato?

+0

Secondo collegamento https://code.google.com/p/android-test-kit/wiki/EspressoSamples#Asserting_that_a_view_is_not_displayed, "L'approccio di cui sopra funziona se la vista fa ancora parte della gerarchia ". Cerca testo su "Asserendo che una vista non viene visualizzata". –

risposta

1

Un modo semplice per verificare la presenza di una visualizzazione o la sua sottoclasse come un pulsante è quello di utilizzare il metodo getVisibility da View classe. Devo fare attenzione che l'attributo di visibilità non è chiaramente definito nel mondo della GUI. Una vista può essere considerata visibile ma può essere sovrapposta ad un'altra vista, per esempio, rendendola nascosta.

Un altro modo, ma più preciso (non l'ho provato) è controllare i limiti rettangolari della vista. Non così semplice

È abbastanza chiaro? non posso darti esempi specifici dato che non hai inserito il codice.

+0

Ho modificato la domanda per renderla più chiara. – user846316

+0

Grazie per l'aggiornamento del codice. Non sapevo che l'Espresso fosse una biblioteca di prova. Ad ogni modo ho postato un'altra risposta. Almeno conosco Java e Android. –

5

Ho ricercato un po 'di espresso, e ho trovato questo @Espresso Samples.

  1. Cerca testo "Affermare che una vista non viene visualizzata". Dice "L'approccio sopra funziona se la vista fa ancora parte della gerarchia". Quindi penso che il tuo codice dovrebbe funzionare, ma devi anche usare ViewAssertions. Utilizzando il codice, forse fare questo:

    if (ViewAssertions.doesNotExist()) == null) { 
        return; 
    } 
    onMyPageOne.check(matches(isDisplayed())); 
    
  2. Un'altra tecnica è di controllo per l'interfaccia utente esistenza. Cerca testo "Asserendo che una vista non è presente". Utilizzando il codice, il mio miglior suggerimento è:

    onMyPageOne.check (doesNotExist());

Nota: questo chiama il metodo doesNotExist.

Il loro codice di esempio è: onView(withId(R.id.bottom_left)).check(doesNotExist());

+3

Questo è quello da usare. Non stavo facendo (isDisplayed()) :( –

2

Il problema è che tutte le assertoin() e check() metodi restituiscono Assertion che interrompe il flusso di test se non è riuscita.

+0

Esattamente questo è il problema! Non so se c'è un modo per farlo.per tutti gli esperti di Espresso? – user846316

+0

questo dovrebbe essere un commento, immagino che –

33

E 'possibile prendere le eccezioni sollevate da Espresso in questo modo:

Se si desidera verificare se un punto di vista è in gerarchia:

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

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

verrà generata Questa eccezione se la vista non è nella gerarchia.

A volte la vista può essere nella gerarchia, ma abbiamo bisogno di testare se viene visualizzata, quindi non c'è un'altra eccezione per le affermazioni, in questo modo:

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

devi aspettare un timeout però, e invece di scherzare con i timeout sarebbe meglio controllare semplicemente "questa cosa è qui, sì o no". L'unica ragione per cui sono qui è che ho bisogno di ridurre i minuti del dispositivo per il test dei dispositivi cloud. basta aspettare 30 secondi per colpire un'eccezione, e gestire contestualmente i timeout è sbagliato –

+0

L'attesa di eccezioni è generalmente un odore di codice, con alcune eccezioni, suppongo come l'analisi di input sconosciuti, ma anche questo è discutibile – RyPope

+0

Mi piace questa risposta, in sostanza la domanda è, se c'è qualche API che può restituire un valore booleano (vero o falso) invece di ViewAssertion per dire all'utente se l'elemento è visibile. i test di prova possono essere codificati di conseguenza. –

5
classe

Utility che consente di verificare se vista è visible, gone o 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; 
     } 
    } 
} 

e il loro utilizzo potrebbe essere la seguente:

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

È possibile utilizzare Matchers.anyOf per controllare se vengono visualizzati uno qualsiasi dei due punti di vista:

onView(
    anyOf(withId(R.id.view_1), withId(R.id.view_2)) 
).check(matches(isDisplayed())); 
+0

Per verificare se viene visualizzata la vista 1 O vista 2, è possibile utilizzare anyOf su viewMatcher. –

+1

Questo codice non funziona per garantire che esca 1 visualizzazione su 2. Sei sicuro che lo faccia? – dira

11

ci sono due casi qui che si potrebbe cercare di coprire. La prima è se si sta verificando se la vista "viene visualizzato sullo schermo per l'utente", nel qual caso si usa isDisplayed()

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

o la negazione

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

L'altro caso è se stai controllando se la vista è visibile ma non necessariamente visualizzata sullo schermo (ad esempio un elemento in una vista a scorrimento). Per questo si può utilizzare withEffectiveVisibility(Visibility)

onView(matcher).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))); 
+0

Grazie @RyPope, il test di visibilità ha funzionato. – user1510006

0
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())); 
    } 
Problemi correlati