Überprüfen Sie, ob mit Espresso ein Dialogfeld angezeigt wird

85

Ich versuche einige Tests mit dem neuen Android-Test-Kit (Espresso) zu schreiben . Ich kann jedoch keine Informationen dazu finden, wie Sie überprüfen können, ob ein Dialogfeld angezeigt wird, und einige Aktionen ausführen (z. B. Klicken auf die positiven und negativen Schaltflächen usw.). Beachten Sie, dass ein Dialogfeld möglicherweise auch von a angezeigt wird WebView, nicht von der Anwendung selbst.

Jede Hilfe wäre dankbar. Ich brauche nur einen Link oder einen Beispielcode für die Grundlagen:

  1. Überprüfen Sie, ob ein Dialogfeld angezeigt wird
  2. Führen Sie Klicks auf Dialogschaltflächen durch
  3. Interagiere mit der inneren Ansicht des Dialogfelds (wenn es sich um eine benutzerdefinierte Ansicht handelt)
  4. Preform klickt außerhalb des Dialogfelds und prüft, ob es angezeigt wird oder nicht (z. B. ob setCancelable(false)es im Dialogfeld- Generator aufgerufen wurde und wir dies überprüfen möchten).

Danke für deinen Rat!

Serj Lotutovici
quelle
Irgendwelche Rückmeldungen zu meiner Antwort unten?
bestreitet

Antworten:

121
  1. Um zu überprüfen, ob ein Dialogfeld angezeigt wird, können Sie einfach überprüfen, ob Ansicht mit einem im Dialogfeld enthaltenen Text angezeigt wird:

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

    oder basierend auf Text mit ID

    onView(withId(R.id.myDialogTextId)).check(matches(allOf(withText(myDialogText), isDisplayed()));
  2. Um auf die Schaltfläche "Dialoge" zu klicken, gehen Sie wie folgt vor (Schaltfläche 1 - OK, Schaltfläche 2 - Abbrechen):

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

    AKTUALISIEREN

  3. Ich denke, ist möglich, da Espresso Multi-Window-Unterstützung hat .
  4. Sie sind sich nicht sicher, ob Sie außerhalb der benutzerdefinierten Dialogansicht klicken sollen, aber um zu überprüfen, ob sie angezeigt wird oder nicht, müssen Sie Ihren benutzerdefinierten Matcher erstellen und darin überprüfen.
leugnet
quelle
3
Schritt 1 hat bei einem ProgressDialog nicht funktioniert. Ich versuche nur, den Titel und die Botschaft des Dialogs zu validieren
Tim Boland
1
Was ist mit Espresso und statischen Importen? Aus welchen Klassen kommen diese Methoden? Warum verwenden Sie statische Importe für eine Stapelüberlaufantwort?
2
@jvrodrigues Jedes einzelne Espresso-Tutorial verwendet statische Importe. Ich würde vorschlagen, dass Sie sich einfach daran gewöhnen (obwohl ich die Frustration verstehe). Dies hilft: google.github.io/android-testing-support-library/docs
AutonomousApps
Für Schritt 4 können Sie "pressBack ()" aufrufen, anstatt außerhalb des Dialogfelds zu klicken. das schließt den Dialog. Dies entspricht der Verwendung der Hardware-Zurück-Taste.
Ethan
@denys Projekt wurde verschoben. es scheint, dass die Verbindung tot ist.
Neon Warge
66

Ich benutze dies derzeit und es scheint gut zu funktionieren.

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

Wenn Sie einen solchen AlertDialog haben:

Geben Sie hier die Bildbeschreibung ein

Sie können überprüfen, ob die Komponenten angezeigt werden:

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

und führen Sie eine Aktion aus:

onView(withId(android.R.id.button3)).perform(click());
Luiz Augusto
quelle
2
Der Text in meinem Fall hatte eine ID android.R.id.messageund der Titel hatte eine versteckte ID von android.R.id.alertTitle.
Jason Robinson
2
Wenn Sie AlertDialog (oder DialogFragment) verwenden, der aus der AppCompat-Unterstützungsbibliothek stammt, verwenden Sie Folgendes:int alertDialogTitleId = android.support.v7.appcompat.R.id.alertTitle;
Mr-IDE
3

Um Frage 4 zu beantworten, die in der akzeptierten Antwort nicht beantwortet wird, habe ich den folgenden Code geändert, den ich hier im Stapelüberlauf ( Link ) gefunden habe, um zu testen, ob ein Toast angezeigt wurde.

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

Die idübergebene ID ist die ID eines Viewaktuell in Ihrem Dialogfeld angezeigten. Sie können die Methode auch folgendermaßen schreiben:

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

Und jetzt sucht es nach Vieweiner bestimmten Textzeichenfolge.

Verwenden Sie es so:

getRootView(getActivity(), R.id.text_id).perform(click());
Autonome Apps
quelle
3

Die Schaltflächen-IDs R.id.button1 und R.id.button2 sind geräteübergreifend nicht identisch. Die IDs können sich mit den Betriebssystemversionen ändern.

Der richtige Weg, dies zu erreichen, ist die Verwendung von UIAutomator. Fügen Sie die UIAutomator-Abhängigkeit in Ihr build.gradle ein

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

und verwenden

// 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
quelle
1
Eigentlich android.R.id.button1, android.R.id.button2und android.R.id.button3für „positiv“, „neutral“ und „negativ“ sind globale Symbole, kann verwendet werden. Wenn Sie Schaltflächen über ihren Text auswählen - was völlig in Ordnung ist -, benötigen Sie UIAutomator nicht, können dies aber auch mit Espresso tun onView(withText("ButtonTest")).perform(click()).
Thomas Keller
Ich habe diese Lösung mit einem Robotium-Testframework verwendet und konnte problemlos Schaltflächen des Android-Betriebssystems auswählen. Hat mir viel Zeit gespart. Danke jaydeepw!
Ray
@ThomasKeller Ich habe in der Vergangenheit die IDs "button1" und "button2" verwendet. Meine Tests sind fehlgeschlagen, als ich sie auf verschiedenen Geräten ausgeführt habe. Der gezeigte Dialog ist die Systemsteuerung. Nicht deine Kontrolle / Benutzeroberfläche. Für alles außerhalb Ihrer Benutzeroberfläche wird UIAutomator empfohlen.
JaydeepW
Das ist es. Vielen Dank.
29.
3

Nur für den Fall, dass jemand wie ich über diese Frage stolpert. Alle Antworten funktionieren nur für Dialoge MIT Dialogschaltflächen. Versuchen Sie nicht, dies für Fortschrittsdialoge ohne Benutzerinteraktion zu verwenden. Espresso wartet darauf, dass die App in den Ruhezustand wechselt. Solange der Fortschrittsdialog sichtbar ist, ist die App nicht inaktiv.

Diana Farin
quelle