Espresso w sieci

Espresso-Web to punkt wejścia do pracy ze komponentami UI Android WebView. Espresso-Web wykorzystuje atom z popularnego interfejsu WebDriver API do badania i kontrolowania działania komponentu WebView.

Kiedy używać Espresso-Web

Skorzystaj z Espresso-Web, by przetestować swoje aplikacje hybrydowe, zwłaszcza integrację natywnych komponentów UI aplikacji z komponentami jej WebView. Interfejsu Espresso-Web API możesz używać w połączeniu z innymi interfejsami API Espresso, by w pełni korzystać z elementów sieciowych wewnątrz obiektów WebView.

Jeśli chcesz przetestować tylko interfejs WebView, a nie interakcje między komponentem WebView a komponentami natywnymi w aplikacji, możesz utworzyć ogólny test witryny, używając platformy takiej jak WebDriver. Jeśli korzystasz ze środowiska do testowania stron internetowych, nie musisz używać urządzenia z Androidem ani maszyny wirtualnej w języku Java, dzięki czemu testy przebiegają szybciej i niezawodnie. Espresso-Web umożliwia ponowne wykorzystywanie niestandardowych atomów WebDriver, co zapewnia dużą elastyczność, zwłaszcza podczas pisania testów, które zamierzasz przeprowadzić zarówno w przypadku samodzielnych aplikacji internetowych, jak i aplikacji zawierających interfejs użytkownika Androida.

Jak to działa

Podobnie jak w przypadku metody onData() Espresso, interakcja WebView składa się z kilku obiektów Atom. Interakcje WebView wykorzystują połączenie języka programowania Java i mostu JavaScript. Nie ma możliwości wprowadzenia warunków wyścigu przez ujawnienie danych ze środowiska JavaScript, więc wszystko, co Espresso widzi po stronie języka Java, to izolowana kopia. W pełni obsługiwane są zwracane dane z obiektów Web.WebInteraction, dzięki czemu możesz zweryfikować wszystkie dane zwracane z żądania.

Co to jest WebDriver Atom?

Platforma WebDriver wykorzystuje zasoby Atoms do programowego znajdowania elementów sieciowych i manipulowania nimi. Atrybut Atom jest używany przez WebDriver do umożliwienia manipulacji przeglądarką. Atom jest koncepcyjnie podobny do ViewAction – samodzielnej jednostki, która wykonuje działanie w interfejsie użytkownika. Ujawniasz Atoms za pomocą listy zdefiniowanych metod, takich jak findElement() czy getElement(), aby sterować przeglądarką z perspektywy użytkownika. Jeśli jednak używasz platformy WebDriver bezpośrednio, musisz zadbać o odpowiednią administrację i wymagać logiki, która jest dość obszerna.

W Espresso klasy Web i Web.WebInteraction opakowują ten stały szablon, nadając im wrażenie interakcji z obiektami WebView w stylu espresso. W kontekście elementu WebView atrybuty Atom są używane jako zamiennik tradycyjnego espresso ViewMatchers i ViewActions.

Interfejs API wygląda wtedy dość prosto:

Kotlin

onWebView()
    .withElement(Atom)
    .perform(Atom)
    .check(WebAssertion)

Java

onWebView()
    .withElement(Atom)
    .perform(Atom)
    .check(WebAssertion);

Więcej informacji znajdziesz w dokumentacji Senenium na temat Atoms.

Implementowanie komponentu WebView

Aby podczas testów aplikacji korzystać z narzędzia WebView, postępuj zgodnie ze wskazówkami podanymi w sekcjach poniżej.

Pakiety

Aby uwzględnić Espresso-Web w swoim projekcie, wykonaj te czynności:

  1. Otwórz plik build.gradle aplikacji. Zwykle nie jest to plik build.gradle najwyższego poziomu, ale app/build.gradle.
  2. Dodaj ten wiersz w zależnościach:

    Odlotowy

        androidTestImplementation 'androidx.test.espresso:espresso-web:3.4.0'
        

    Kotlin

        androidTestImplementation('androidx.test.espresso:espresso-web:3.4.0')
        
  3. Espresso-Web jest zgodny tylko z Espresso 2.2 lub nowszym oraz z biblioteką testową w wersji 0.3 lub nowszej, więc pamiętaj o zaktualizowaniu tych wierszy:

    Odlotowy

        androidTestImplementation 'androidx.test:runner:1.4.0'
        androidTestImplementation 'androidx.test:rules:1.4.0'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
        

    Kotlin

        androidTestImplementation('androidx.test:runner:1.4.0')
        androidTestImplementation('androidx.test:rules:1.4.0')
        androidTestImplementation('androidx.test.espresso:espresso-core:3.4.0')
        

Typowe zastosowanie interfejsu API

Metoda onWebView() jest głównym punktem wejścia podczas pracy z WebView na Androidzie przy użyciu Espresso. Ta metoda służy do wykonywania testów Espresso-Web, takich jak:

Kotlin

onWebView()
    .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...))
    .perform(webClick()) // Similar to perform(click())

    // Similar to check(matches(...))
    .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")))

Java

onWebView()
    .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...))
    .perform(webClick()) // Similar to perform(click())

    // Similar to check(matches(...))
    .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")));

W tym przykładzie Espresso-Web lokalizuje element DOM, którego identyfikator to "link_2", i go klika. Następnie narzędzie sprawdzi, czy WebView wysyła żądanie GET zawierające ciąg tekstowy "navigation_2.html".

Obsługa JavaScriptu

Podczas testów system wykonuje wszystkie interakcje z komponentem WebView przy użyciu JavaScriptu. Dlatego, aby umożliwić ocenę JavaScriptu, testowany komponent WebView musi mieć włączony język JavaScript.

Możesz wymusić włączenie JavaScriptu, wywołując metodę forceJavascriptEnabled() jako działanie w testowanej aktywności, jak widać w tym fragmencie kodu.

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule val activityScenarioRule =
        activityScenarioRule<MyWebViewActivity>()

    @Test fun testWebViewInteraction() {
        onWebView().forceJavascriptEnabled()
    }
}

Typowe interakcje w internecie

Typowe interakcje z obiektami Web.WebInteraction to:

  • withElement() odwołuje się do elementu DOM w komponencie WebView.

    Przykład:

    Kotlin

    onWebView().withElement(findElement(Locator.ID, "teacher"))
    

    Java

    onWebView().withElement(findElement(Locator.ID, "teacher"));
    
  • withContextualElement() odwołuje się do elementu DOM o zakresie ograniczonym w komponencie WebView w stosunku do innego elementu DOM. Należy najpierw wywołać withElement(), aby ustanowić referencyjny obiekt Web.WebInteraction (element DOM).

    Przykład:

    Kotlin

    .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))
    

    Java

    .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"));
    
  • check() ocenia warunek, sprawdzając, czy przyjmuje wartość true.

    Przykład:

    Kotlin

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))
        .check(webMatches(getText(), containsString("Socrates")))
    

    Java

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))
        .check(webMatches(getText(), containsString("Socrates")));
    
  • perform() wykonuje działanie w komponencie WebView, na przykład klika element.

    Przykład:

    Kotlin

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .perform(webClick())
    

    Java

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .perform(webClick());
    
  • reset() przywraca WebView do stanu początkowego. Jest to konieczne, gdy wcześniejsze działanie, takie jak kliknięcie, spowoduje zmianę nawigacji, przez co obiekty ElementReference i WindowReference staną się niedostępne.

    Uwaga: chociaż użycie reset() jest przydatne podczas tworzenia asercji dotyczących przepływów pracy na wielu stronach, takich jak przesyłanie formularzy, powinno być zwykle ograniczone i koncentrować się na jednej stronie.

    Przykład:

    Kotlin

    onWebView()
        .withElement(...)
        .perform(...)
        .reset()
    

    Java

    onWebView()
        .withElement(...)
        .perform(...)
        .reset();
    

Przykład

W tym przykładzie sprawdzisz, czy po wpisaniu tekstu w komponencie WebView i wybraniu przycisku Prześlij ten sam tekst pojawia się w innym elemencie w tym samym komponencie WebView:

Kotlin

const val MACCHIATO = "Macchiato"

@RunWith(AndroidJUnit4::class)
class MyEspressoWebTestSuite {

    @Test fun typeTextInInput_clickButton_SubmitsForm() {
        // Create an intent that displays a web form.
        val webFormIntent = Intent()
        // ...

        // Lazily launch the Activity with a custom start Intent per test.
        ActivityScenario.launchActivity(webFormIntent)

        // Selects the WebView in your layout. If you have multiple WebView
        // objects, you can also use a matcher to select a given WebView,
        // onWebView(withId(R.id.web_view)).
        onWebView()
            // Find the input element by ID.
            .withElement(findElement(Locator.ID, "text_input"))

            // Clear previous input and enter new text into the input element.
            .perform(clearElement())
            .perform(DriverAtoms.webKeys(MACCHIATO))

            // Find the "Submit" button and simulate a click using JavaScript.
            .withElement(findElement(Locator.ID, "submitBtn"))
            .perform(webClick())

            // Find the response element by ID, and verify that it contains the
            // entered text.
            .withElement(findElement(Locator.ID, "response"))
            .check(webMatches(getText(), containsString(MACCHIATO)))
    }
}

Java

public static final String MACCHIATO = "Macchiato";

@Test
public void typeTextInInput_clickButton_SubmitsForm() {
    // Create an intent that displays a web form.
    Intent webFormIntent = new Intent();
    // ...

    // Lazily launch the Activity with a custom start Intent per test.
    ActivityScenario.launchActivity(webFormIntent);

    // Selects the WebView in your layout. If you have multiple WebView objects,
    // you can also use a matcher to select a given WebView,
    // onWebView(withId(R.id.web_view)).
    onWebView()
        // Find the input element by ID.
        .withElement(findElement(Locator.ID, "text_input"))

        // Clear previous input and enter new text into the input element.
        .perform(clearElement())
        .perform(DriverAtoms.webKeys(MACCHIATO))

        // Find the "Submit" button and simulate a click using JavaScript.
        .withElement(findElement(Locator.ID, "submitBtn"))
        .perform(webClick())

        // Find the response element by ID, and verify that it contains the
        // entered text.
        .withElement(findElement(Locator.ID, "response"))
        .check(webMatches(getText(), containsString(MACCHIATO)));
}

Dodatkowe materiały

Więcej informacji o korzystaniu z Espresso-Web w testach na Androidzie znajdziesz w tych materiałach.

Próbki

  • WebbasicSample: używa Espresso-Web do interakcji z obiektami WebView.