Verificare se viene visualizzata una finestra di dialogo con Espresso


87

Sto cercando di scrivere alcuni test con il nuovo Android-test-kit (Espresso) . Ma non riesco a trovare alcuna informazione su come controllare se una finestra di dialogo è visualizzata ed eseguire alcune azioni su di essa (come fare clic sui pulsanti positivo e negativo, ecc.). Notare che una finestra di dialogo può essere visualizzata anche da a WebView, non dall'applicazione stessa.

Qualsiasi aiuto sarebbe apprezzato. Ho solo bisogno di un collegamento o di un codice di esempio per le basi:

  1. Controlla se viene visualizzata una finestra di dialogo
  2. Eseguire clic sui pulsanti di dialogo
  3. Interagisci con la vista interna della finestra di dialogo (se è una vista personalizzata)
  4. La preforma fa clic all'esterno della finestra di dialogo e controlla se viene visualizzata o meno (ad esempio, se setCancelable(false) stato chiamato nel generatore di finestre di dialogo e vogliamo verificarlo)

Grazie del consiglio!


Qualche feedback sulla mia risposta qui sotto ??
nega il

Risposte:


125
  1. Per verificare se appare la finestra di dialogo puoi semplicemente controllare se Visualizza con un testo presente all'interno della finestra di dialogo è mostrato:

    onView(withText("dialogText")).check(matches(isDisplayed()));
    

    oppure, in base al testo con ID

    onView(withId(R.id.myDialogTextId)).check(matches(allOf(withText(myDialogText), isDisplayed()));
    
  2. Per fare clic sul pulsante delle finestre di dialogo, eseguire questa operazione (pulsante1 - OK, pulsante2 - Annulla):

    onView(withId(android.R.id.button1)).perform(click());
    

    AGGIORNARE

  3. Penso che sia possibile poiché Espresso ha il supporto multi finestra .
  4. Non sono sicuro di fare clic al di fuori della visualizzazione della finestra di dialogo personalizzata, ma per verificare se viene visualizzata o meno, devi creare il tuo abbinamento personalizzato e controllare al suo interno.

3
Il passaggio 1 non ha funzionato per me su ProgressDialog. Sto solo cercando di convalidare il titolo e il messaggio del dialogo
Tim Boland,

1
Cos'è l'espresso e le importazioni statiche? Da quali classi provengono questi metodi? Perché stai usando importazioni statiche su una risposta di overflow dello stack?

2
@jvrodrigues ogni singolo tutorial Espresso utilizza importazioni statiche. Ti suggerirei di abituarti (anche se capisco la frustrazione). Questo aiuta: google.github.io/android-testing-support-library/docs
AutonomousApps

Per il passaggio 4 invece di fare clic fuori dalla finestra di dialogo puoi chiamare "pressBack ();" che chiude la finestra di dialogo. è l'equivalente di utilizzare il pulsante hardware indietro.
Ethan

Il progetto @denys è stato spostato. sembra che il collegamento sia morto.
Neon Warge

67

Attualmente lo uso e sembra funzionare bene.

onView(withText(R.string.my_title))
    .inRoot(isDialog()) // <---
    .check(matches(isDisplayed()));

28

Se hai un AlertDialog come questo:

inserisci qui la descrizione dell'immagine

È possibile verificare se i componenti vengono visualizzati:

int titleId = mActivityTestRule.getActivity().getResources()
        .getIdentifier( "alertTitle", "id", "android" );

onView(withId(titleId))
        .inRoot(isDialog())
        .check(matches(withText(R.string.my_title)))
        .check(matches(isDisplayed()));

onView(withId(android.R.id.text1))
        .inRoot(isDialog())
        .check(matches(withText(R.string.my_message)))
        .check(matches(isDisplayed()));

onView(withId(android.R.id.button2))
        .inRoot(isDialog())
        .check(matches(withText(android.R.string.no)))
        .check(matches(isDisplayed()));

onView(withId(android.R.id.button3))
        .inRoot(isDialog())
        .check(matches(withText(android.R.string.yes)))
        .check(matches(isDisplayed()));

ed eseguire un'azione:

onView(withId(android.R.id.button3)).perform(click());

2
Il testo nel mio caso aveva l'ID android.R.id.messagee il titolo aveva l'ID nascosto di android.R.id.alertTitle.
Jason Robinson

2
Se utilizzi AlertDialog (o DialogFragment) che proviene dalla libreria di supporto di AppCompat, usa questo:int alertDialogTitleId = android.support.v7.appcompat.R.id.alertTitle;
Mr-IDE

Nel caso in cui qualcuno abbia bisogno di conoscere i valori dei parametri, stackoverflow.com/a/15488321/1713366 . Se non conosci il nome o il tipo di def, prova a check()visualizzare una vista che non esiste e guarda la gerarchia del layout su logcat. Vedrai un sacco di questi defType = name. Ad esempio, il message=hello worldtuo parametro dovrebbe essere simile a"hello world", "message", "your package name"
Jcorretjer

3

Per rispondere alla domanda 4, che la risposta accettata non fa, ho modificato il seguente codice, che ho trovato qui su Stack Overflow ( link ) per verificare se era visualizzato un avviso popup.

@NonNull
public static ViewInteraction getRootView(@NonNull Activity activity, @IdRes int id) {
    return onView(withId(id)).inRoot(withDecorView(not(is(activity.getWindow().getDecorView()))));
}

Il idpassato è l'id di un Viewattualmente visualizzato nella tua finestra di dialogo. Puoi anche scrivere il metodo in questo modo:

@NonNull
public static ViewInteraction getRootView(@NonNull Activity activity, @NonNull String text) {
    return onView(withText(text)).inRoot(withDecorView(not(is(activity.getWindow().getDecorView()))));
}

E ora sta cercando un Viewcontenente una particolare stringa di testo.

Usalo così:

getRootView(getActivity(), R.id.text_id).perform(click());

3

I pulsanti ID R.id.button1 e R.id.button2 non saranno gli stessi su tutti i dispositivi. Gli ID possono cambiare con le versioni del sistema operativo.

Il modo corretto per ottenere ciò è utilizzare UIAutomator. Includi la dipendenza UIAutomator nel tuo build.gradle

// Set this dependency to build and run UI Automator tests
  androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'

e utilizzare

// Initialize UiDevice instance
UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());

// Search for correct button in the dialog.
UiObject button = uiDevice.findObject(new UiSelector().text("ButtonText"));
if (button.exists() && button.isEnabled()) {
    button.click();
}

1
In realtà, android.R.id.button1, android.R.id.button2e android.R.id.button3per "positivo", "folle" e "negativo", sono simboli globali che possono essere utilizzati. Se scegli di selezionare i pulsanti tramite il loro testo - che va benissimo - non hai bisogno di UIAutomator, ma puoi fare lo stesso con Espresso's onView(withText("ButtonTest")).perform(click()).
Thomas Keller

Ho usato questa soluzione con un framework di test Robotium e sono stato in grado di selezionare facilmente i pulsanti della finestra di dialogo del sistema operativo Android. Mi ha fatto risparmiare un sacco di tempo. Grazie jaydeepw!
Ray

@ThomasKeller Ho usato button1, button2 id in passato, i miei test si sono interrotti quando li ho eseguiti su una varietà di dispositivi. La finestra di dialogo mostrata è il controllo del sistema. Non è il tuo controllo / interfaccia utente. Per qualsiasi cosa al di fuori della tua interfaccia utente, si consiglia UIAutomator.
JaydeepW

Questo è tutto. Grazie mille.
1lb3r

3

Nel caso qualcuno si imbattesse in questa domanda come ho fatto io. Tutte le risposte funzioneranno solo per le finestre di dialogo CON i pulsanti di dialogo. Non provare a utilizzarlo per finestre di dialogo di avanzamento senza l'interazione dell'utente. Espresso continua ad aspettare che l'app entri in uno stato di inattività. Finché la finestra di dialogo di avanzamento è visibile, l'app non è inattiva.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.