Vérifiez si une boîte de dialogue s'affiche avec Espresso

86

J'essaye d'écrire quelques tests avec le nouveau kit de test android (Espresso) . Mais je ne trouve aucune information sur la façon de vérifier si une boîte de dialogue est affichée et d'effectuer certaines actions dessus (comme cliquer sur les boutons positifs et négatifs, etc.). Notez qu'une boîte de dialogue peut également être affichée par a WebView, pas par l'application elle-même.

Toute aide serait appréciée. J'ai juste besoin d'un lien ou d'un exemple de code pour les bases:

  1. Vérifiez si une boîte de dialogue apparaît
  2. Effectuer des clics sur les boutons de la boîte de dialogue
  3. Interagir avec la vue intérieure de la boîte de dialogue (s'il s'agit d'une vue personnalisée)
  4. Préformez les clics en dehors de la boîte de dialogue et vérifiez si elle s'affiche ou non (par exemple, si elle a setCancelable(false)été appelée sur le générateur de boîte de dialogue et que nous voulons vérifier cela)

Merci pour les conseils!

Serj Lotutovici
la source
Des commentaires sur ma réponse ci-dessous ??
denys le

Réponses:

123
  1. Pour vérifier si la boîte de dialogue apparaît, vous pouvez simplement vérifier si la vue avec un texte présent à l'intérieur de la boîte de dialogue est affichée:

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

    ou, basé sur un texte avec identifiant

    onView(withId(R.id.myDialogTextId)).check(matches(allOf(withText(myDialogText), isDisplayed()));
    
  2. Pour cliquer sur le bouton des boîtes de dialogue, procédez comme suit (button1 - OK, button2 - Cancel):

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

    MISE À JOUR

  3. Je pense que c'est possible car Espresso prend en charge plusieurs fenêtres .
  4. Vous n'êtes pas sûr de cliquer en dehors de la vue de la boîte de dialogue personnalisée, mais pour vérifier si elle s'affiche ou non, vous devez créer votre correspondance personnalisée et vérifier à l'intérieur.
nie
la source
3
L'étape 1 n'a pas fonctionné pour moi sur un ProgressDialog. J'essaie juste de valider le titre et le message du dialogue
Tim Boland
1
Qu'en est-il des importations d'espresso et statiques? De quelles classes proviennent ces méthodes? Pourquoi utilisez-vous des importations statiques sur une réponse de débordement de pile?
2
@jvrodrigues, chaque didacticiel Espresso utilise des importations statiques. Je vous suggère de vous y habituer (même si je comprends la frustration). Cela aide: google.github.io/android-testing-support-library/docs
AutonomousApps
Pour l'étape 4, au lieu de cliquer en dehors de la boîte de dialogue, vous pouvez appeler "pressBack ();" qui rejette le dialogue. c'est l'équivalent d'utiliser le bouton de retour matériel.
Ethan le
Le projet @denys a été déplacé. il semble que le lien est mort.
Neon Warge
67

J'utilise actuellement ceci et cela semble fonctionner correctement.

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

Si vous avez un AlertDialog comme ça:

entrez la description de l'image ici

Vous pouvez vérifier si les composants sont affichés:

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()));

et effectuez une action:

onView(withId(android.R.id.button3)).perform(click());
Luiz Augusto
la source
2
Le texte dans mon cas avait id android.R.id.messageet le titre avait un identifiant caché de android.R.id.alertTitle.
Jason Robinson
2
Si vous utilisez AlertDialog (ou DialogFragment) qui provient de la bibliothèque de support AppCompat, utilisez ceci:int alertDialogTitleId = android.support.v7.appcompat.R.id.alertTitle;
Mr-IDE
3

Pour répondre à la question 4, que la réponse acceptée ne fait pas, j'ai modifié le code suivant, que j'ai trouvé ici sur Stack Overflow ( lien ) pour tester si un Toast était affiché.

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

Le idpassé est l'id d'un Viewactuellement affiché dans votre boîte de dialogue. Vous pouvez également écrire la méthode comme ceci:

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

Et maintenant, il recherche un Viewcontenant une chaîne de texte particulière.

Utilisez-le comme ceci:

getRootView(getActivity(), R.id.text_id).perform(click());
AutonomousApps
la source
3

Les identifiants de bouton R.id.button1 et R.id.button2 ne seront pas identiques sur tous les appareils. Les identifiants peuvent changer avec les versions du système d'exploitation.

La bonne façon d'y parvenir est d'utiliser UIAutomator. Incluez la dépendance UIAutomator dans votre build.gradle

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

et utilise

// 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();
}
JaydeepW
la source
1
En fait, android.R.id.button1, android.R.id.button2et android.R.id.button3pour « positive », « neutre » et « négatif », sont des symboles globaux qui peuvent être utilisés. Si vous choisissez de sélectionner des boutons via leur texte - ce qui est tout à fait correct - vous n'avez pas besoin d'UIAutomator, mais vous pouvez faire de même avec Espresso onView(withText("ButtonTest")).perform(click()).
Thomas Keller
J'ai utilisé cette solution avec un framework de test Robotium et j'ai pu sélectionner facilement les boutons de la boîte de dialogue Android OS. Cela m'a fait gagner du temps. Merci jaydeepw!
Ray
@ThomasKeller J'ai utilisé des identifiants button1, button2 dans le passé, mes tests ont été interrompus lorsque je les ai exécutés sur divers appareils. La boîte de dialogue affichée est la commande système. Pas votre contrôle / interface utilisateur. Pour tout ce qui se trouve en dehors de votre interface utilisateur, UIAutomator est recommandé.
JaydeepW
C'est ça. Merci beaucoup.
1lb3r le
3

Juste au cas où quelqu'un trébucherait sur cette question comme moi. Toutes les réponses ne fonctionneront que pour les boîtes de dialogue AVEC des boutons de dialogue. N'essayez pas de l'utiliser pour les boîtes de dialogue de progression sans intervention de l'utilisateur. Espresso attend que l'application entre en mode veille. Tant que la boîte de dialogue de progression est visible, l'application n'est pas inactive.

Diana Farin
la source