Sprawdź, czy wyświetla się okno dialogowe z Espresso

86

Próbuję napisać kilka testów z nowym zestawem testowym na Androida (Espresso) . Ale nie mogę znaleźć żadnych informacji, jak sprawdzić, czy okno dialogowe jest wyświetlane i wykonać w nim pewne czynności (np. Kliknięcie przycisków pozytywów i negatywów itp.). Zwróć uwagę, że okno dialogowe może być również wyświetlane przez a WebView, a nie przez samą aplikację.

Każda pomoc będzie mile widziana. Potrzebuję tylko linku lub przykładowego kodu do podstaw:

  1. Sprawdź, czy pojawi się okno dialogowe
  2. Wykonaj kliknięcia przycisków dialogowych
  3. Interakcja z widokiem wewnętrznym okna dialogowego (jeśli jest to widok niestandardowy)
  4. Preform klika poza oknem dialogowym i sprawdź, czy się wyświetla (na przykład czy setCancelable(false)został wywołany w kreatorze okien dialogowych i chcemy to sprawdzić)

Dziękuję z góry!

Serj Lotutovici
źródło
Jakieś uwagi na temat mojej odpowiedzi poniżej?
denys

Odpowiedzi:

123
  1. Aby sprawdzić, czy pojawi się okno dialogowe, możesz po prostu sprawdzić, czy jest wyświetlany widok z tekstem obecnym w oknie dialogowym:

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

    lub na podstawie tekstu o identyfikatorze

    onView(withId(R.id.myDialogTextId)).check(matches(allOf(withText(myDialogText), isDisplayed()));
    
  2. Aby kliknąć przycisk okna dialogowego, wykonaj następujące czynności (przycisk1 - OK, przycisk2 - Anuluj):

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

    AKTUALIZACJA

  3. Myślę, że jest to możliwe, ponieważ Espresso obsługuje wiele okien .
  4. Nie jestem pewien co do kliknięcia poza widokiem niestandardowego okna dialogowego, ale aby sprawdzić, czy się wyświetla, czy nie, musisz utworzyć niestandardowy element dopasowujący i sprawdzić w nim.
denys
źródło
3
Krok 1 nie zadziałał dla mnie w ProgressDialog. Próbuję tylko potwierdzić tytuł i przesłanie okna dialogowego
Tim Boland,
1
O co chodzi z espresso i statycznym importem? Z jakich klas pochodzą te metody? Dlaczego używasz importu statycznego w odpowiedzi przepełnienia stosu?
2
@jvrodrigues każdy samouczek dotyczący Espresso używa importu statycznego. Proponuję po prostu przyzwyczaić się do tego (chociaż rozumiem frustrację). To pomaga: google.github.io/android-testing-support-library/docs
AutonomousApps,
W kroku 4 zamiast klikania poza oknem dialogowym możesz wywołać "pressBack ();" co zamyka okno dialogowe. jest to odpowiednik użycia sprzętowego przycisku Wstecz.
Ethan
Projekt @denys został przeniesiony. wygląda na to, że link nie działa.
Neon Warge
67

Obecnie używam tego i wydaje się, że działa dobrze.

onView(withText(R.string.my_title))
    .inRoot(isDialog()) // <---
    .check(matches(isDisplayed()));
kiruwka
źródło
27

Jeśli masz taki AlertDialog:

wprowadź opis obrazu tutaj

Możesz sprawdzić, czy komponenty są wyświetlane:

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

i wykonaj czynność:

onView(withId(android.R.id.button3)).perform(click());
Luiz Augusto
źródło
2
Tekst w moim przypadku miał identyfikator, android.R.id.messagea tytuł miał ukryty identyfikator android.R.id.alertTitle.
Jason Robinson
2
Jeśli używasz AlertDialog (lub DialogFragment), który pochodzi z biblioteki wsparcia AppCompat, użyj tego:int alertDialogTitleId = android.support.v7.appcompat.R.id.alertTitle;
Mr-IDE
3

Aby odpowiedzieć na pytanie 4, na które zaakceptowana odpowiedź nie odpowiada, zmodyfikowałem następujący kod, który znalazłem tutaj na Stack Overflow ( link ), aby sprawdzić, czy wyświetlono Toast.

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

idPrzekazany jest id tematyce Viewaktualnie wyświetlane w oknie dialogowym. Możesz również napisać taką metodę:

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

A teraz szuka Viewokreślonego ciągu tekstowego.

Użyj go w ten sposób:

getRootView(getActivity(), R.id.text_id).perform(click());
AutonomousApps
źródło
3

Ids R.id.button1 i R.id.button2 nie będą takie same na różnych urządzeniach. Identyfikatory mogą się zmieniać wraz z wersjami systemu operacyjnego.

Prawidłowym sposobem osiągnięcia tego jest użycie UIAutomator. Uwzględnij zależność UIAutomator w pliku build.gradle

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

I użyć

// 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();
}
Jaydeep W.
źródło
1
Właściwie android.R.id.button1, android.R.id.button2a android.R.id.button3za „pozytywny”, „neutralny” i „negatywne”, to symbole globalne, które mogą być użyte. Jeśli zdecydujesz się wybierać przyciski za pomocą ich tekstu - co jest całkowicie w porządku - nie potrzebujesz UIAutomator, ale możesz zrobić to samo z Espresso onView(withText("ButtonTest")).perform(click()).
Thomas Keller,
Użyłem tego rozwiązania z platformą testową Robotium i mogłem z łatwością wybierać przyciski okna dialogowego systemu operacyjnego Android. Zaoszczędziło mi to sporo czasu. Dzięki jaydeepw!
Ray
@ThomasKeller W przeszłości używałem identyfikatorów button1, button2, moje testy zepsuły się, gdy uruchomiłem je na różnych urządzeniach. Pokazane okno dialogowe to element sterujący systemu. Nie twoja kontrola / interfejs użytkownika. W przypadku wszystkiego poza interfejsem użytkownika zalecany jest UIAutomator.
Jaydeep W
Otóż ​​to. Dziękuję bardzo.
1lb3r
3

Na wypadek, gdyby ktoś tak jak ja natknął się na to pytanie. Wszystkie odpowiedzi będą działać tylko dla okien dialogowych Z przyciskami dialogowymi. Nie próbuj używać tego do okien dialogowych postępu bez interakcji użytkownika. Espresso ciągle czeka, aż aplikacja przejdzie w stan bezczynności. Dopóki okno dialogowe postępu jest widoczne, aplikacja nie jest bezczynna.

Diana Farin
źródło