Espresso — co to jest, zasady działania i jak używać

Autor: IT Sectr Opublikowano: 2026-04-08 Czas czytania: 8 min

Espresso to framework do zautomatyzowanego testowania UI aplikacji Android, opracowany przez zespół Google i wchodzący w skład AndroidX Test. W przeciwieństwie do testów instrumentalnych, które sprawdzają izolowane komponenty, Espresso współdziała z rzeczywistym UI: klika przyciski, wprowadza tekst, sprawdza wyświetlanie elementów. Według Google Android Developers, Espresso zapewnia automatyczną synchronizację z wątkiem UI, co eliminuje konieczność ręcznego Thread.sleep().

Najważniejsze

  • Espresso — framework do testowania UI Android z automatyczną synchronizacją wątków.
  • ViewMatcher — wyszukiwanie elementu View na ekranie po ID, tekście, hierarchii nadrzędnej.
  • ViewAction — działanie na elemencie: kliknięcie, wprowadzenie tekstu, przesunięcie.
  • ViewAssertion — sprawdzenie stanu elementu: jest wyświetlany, zawiera tekst, jest aktywny.
  • Idling Resource — mechanizm oczekiwania na zakończenie operacji asynchronicznych przed sprawdzeniem UI.

Czym jest Espresso?

Espresso to biblioteka do pisania zautomatyzowanych testów UI dla Androida, która wchodzi w skład Google AndroidX Test. Udostępnia API do wyszukiwania elementów View na ekranie, wykonywania na nich działań (kliknięcie, wprowadzanie, przesunięcie) i sprawdzania ich stanu (jest wyświetlany, zawiera tekst, jest aktywny).

Kluczową cechą Espresso jest automatyczna synchronizacja z głównym wątkiem aplikacji. Framework oczekuje na zakończenie wszystkich zadań asynchronicznych (korutyny, AsyncTask, Handler) przed wykonaniem kolejnego sprawdzenia. Eliminuje to flaky-testy związane z race condition i sprawia, że testy UI są stabilne i niezawodne — żaden test nie zawiera Thread.sleep() ani pętli oczekiwania.

Espresso stosuje zasadę Three-Legged Dog — test składa się z trzech kroków: znajdź element (ViewMatcher), wykonaj działanie (ViewAction), sprawdź wynik (ViewAssertion). Wszystkie trzy kroki zapisywane są w łańcuchu wywołań onView().perform().check(). Ta koncepcja sprawia, że testy są przewidywalne i łatwe do czytania — każdy test wyraźnie opisuje, czego szuka, co robi i co sprawdza.

Jak działa Espresso

Architektura Espresso opiera się na trzech komponentach: Espresso (punkt wejścia — statyczne metody onView i onData), ViewMatchers (wyszukiwanie elementów), ViewActions (działania) i ViewAssertions (sprawdzenia). Wewnętrznie framework wykorzystuje Idling Resource do synchronizacji z wątkiem UI.

Podstawowy test Espresso

Najprostszy test znajduje przycisk po ID, wykonuje kliknięcie i sprawdza, czy pojawił się tekst „Gotowe“. Wszystkie operacje wykonywane są synchronicznie z perspektywy testu — Espresso gwarantuje, że wątek UI zakończył przetwarzanie zdarzenia zanim test będzie kontynuowany. Osiąga się to dzięki wbudowanemu mechanizmowi oczekiwania: onView blokuje wykonanie testu, dopóki UI nie stanie się stabilne.

kotlin
@Test
fun buttonClick_showsSuccessText() {
    // Znajdź przycisk po ID i kliknij
    onView(withId(R.id.button_submit))
        .perform(click())

    // Sprawdź, że tekst „Gotowe“ jest wyświetlany
    onView(withText("Gotowe"))
        .check(matches(isDisplayed()))
}

Reguła ActivityScenario

Do uruchomienia testu Espresso używa się ActivityScenario (AndroidX Test), który tworzy Activity w żądanym stanie — uruchomiona, wstrzymana, zniszczona. ActivityScenario pozwala testować cykl życia Activity oprócz czystego UI. Można na przykład sprawdzić, czy dane są zapisywane podczas obrotu ekranu (rekreacja Activity) i przywracane po zniszczeniu.

ViewMatchers to zestaw metod z klasy Espresso.onView, które pozwalają znaleźć View na ekranie według różnych kryteriów: identyfikatora zasobu (R.id), tekstu, podpowiedzi hint, elementu nadrzędnego i hierarchii. Jeśli jeden matcher nie daje unikalnego wyniku, matchery łączy się przez allOf().

MatcherPrzeznaczenie
withId(R.id.name)Wyszukiwanie po ID zasobu
withText("tekst")Wyszukiwanie po wyświetlanym tekście
withHint("podpowiedź")Wyszukiwanie po atrybucie hint EditText
isDisplayed()Sprawdzenie, czy element jest widoczny na ekranie
hasSibling(matcher)Wyszukiwanie po sąsiednim elemencie
allOf(m1, m2)Kombinacja wielu matcherów

Kombinacja matcherów

Jeśli na ekranie znajduje się kilka identycznych elementów (np. dwa TextView z różnym tekstem), wygodnie jest łączyć matchery przez allOf: onView(allOf(withId(R.id.title), withText("Cześć"))). Gwarantuje to wybór pojedynczego elementu. Operator odwrotny — not() — wyklucza elementy z wyszukiwania, a hasSibling() szuka elementu obok znanego.

ViewActions: interakcja z UI

ViewActions to działania, które Espresso wykonuje na znalezionym View: click(), typeText(), clearText(), scrollTo(), swipeLeft() i inne. Działania przekazywane są do metody perform(), która może przyjmować kilka działań po kolei.

Łańcuch działań

Metoda perform() przyjmuje vararg ViewAction, co pozwala wykonać sekwencję działań na jednym elemencie: wyczyść pole, wprowadź nowy tekst, zamknij klawiaturę i kliknij przycisk. Wszystkie działania są wykonywane w kolejności ich wyliczenia, a Espresso gwarantuje, że poprzednie działanie zostało zakończone przed rozpoczęciem następnego.

kotlin
// Wprowadzanie tekstu w EditText i kliknięcie przycisku
onView(withId(R.id.edit_email))
    .perform(
        clearText(),
        typeText("user@example.com"),
        closeSoftKeyboard()
    )

onView(withId(R.id.button_login))
    .perform(click())

Sprawdzenie przez onData

Dla elementów wewnątrz AdapterView (ListView, RecyclerView) używa się metody onData() zamiast onView. Działa ona z danymi adaptera, a nie z View — znajduje element po zawartości modelu i zwraca odpowiedni View do dalszych działań. onData używa matcherów hamcrest do wyszukiwania elementu po polach modelu danych.

ViewAssertions: sprawdzanie stanu

ViewAssertions sprawdzają, czy View znajduje się w określonym stanie. Podstawowa metoda — matches(matcher), która sprawdza, czy element odpowiada zadanemu matcherowi. Dodatkowo Espresso oferuje doesNotExist() (element nie istnieje) i selectedDescendantsMatch() (sprawdzenie elementów zagnieżdżonych).

Typowe sprawdzenia

Najczęstsze sprawdzenia w testach UI: element jest wyświetlany (isDisplayed), element zawiera określony tekst (withText), element jest aktywny (isEnabled), element nie jest zaznaczony (isNotChecked). Każde sprawdzenie zgłasza szczegółowy wyjątek w przypadku niepowodzenia — z podaniem hierarchii View na ekranie. Ułatwia to debugowanie: w komunikacie błędu widać, jakie elementy rzeczywiście znajdowały się na ekranie w momencie sprawdzenia.

Niestandardowe ViewAssertions

Jeśli standardowe sprawdzenia są niewystarczające, można stworzyć własne poprzez interfejs ViewAssertion. Niestandardowy assertion otrzymuje View i może sprawdzić jego stan programowo — na przykład kolor tekstu, marginesy lub stan niestandardowego komponentu, nieujawnionego przez standardowe matchery.

kotlin
// Sprawdzenie: TextView jest wyświetlane i zawiera tekst
onView(withId(R.id.text_welcome))
    .check(matches(isDisplayed()))
    .check(matches(withText("Witaj")))

// Sprawdzenie: element NIE jest wyświetlany
onView(withId(R.id.progress_bar))
    .check(doesNotExist())

Idling Resources dla operacji asynchronicznych

Idling Resource to mechanizm Espresso do synchronizacji testu z operacjami asynchronicznymi. Domyślnie Espresso oczekuje na zakończenie Handler, AsyncTask i korutyn (przez coroutinesIdlingResource). Jeśli aplikacja wykonuje pracę w tle przez własne wątki lub usługi Callback, należy zarejestrować niestandardowy Idling Resource.

Przykład z korutynami

Począwszy od AndroidX Test 1.4.0, Espresso obsługuje korutyny przez CoroutinesIdlingResource. Test automatycznie oczekuje na zakończenie wszystkich uruchomionych korutyn przed wykonaniem sprawdzeń UI. W przypadku bardziej złożonych scenariuszy używa się CountingIdlingResource — licznika, który jest inkrementowany przy starcie zadania i dekrementowany przy jego zakończeniu.

kotlin
// Rejestracja IdlingResource dla OkHttp
class OkHttpIdlingResource(
    private val client: OkHttpClient
) : IdlingResource {

    private var isIdle = true
    private var watcher: IdlingResource.ResourceCallback? = null

    override fun getName() = "OkHttp"

    override fun isIdleNow() = isIdle

    override fun registerIdleTransitionCallback(
        callback: IdlingResource.ResourceCallback
    ) {
        watcher = callback
    }
}

Konfiguracja Espresso w projekcie Android

Podłączenie Espresso w projekcie Android wykonuje się przez dodanie zależności w build.gradle poziomu modułu. Espresso wchodzi w skład AndroidX Test, więc wystarczy wskazać zależności dla jądra Espresso, rozszerzeń i integracji JUnit. Testy umieszcza się w katalogu src/androidTest i uruchamia na fizycznym urządzeniu lub emulatorze przez AndroidJUnitRunner.

Konfiguracja Gradle

Minimalny zestaw zależności obejmuje espresso-core (jądro), espresso-contrib (dodatkowe matchery dla RecyclerView, Drawer, Picker) i runner (testowy runner AndroidX). Wszystkie testy uruchamiane są na emulatorze lub fizycznym urządzeniu przez Android Test Orchestrator.

kotlin
// build.gradle.kts (zależności androidTest)
android {
    defaultConfig {
        testInstrumentationRunner =
            "androidx.test.runner.AndroidJUnitRunner"
    }
}

dependencies {
    androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
    androidTestImplementation("androidx.test.espresso:espresso-contrib:3.6.1")
    androidTestImplementation("androidx.test:runner:1.6.1")
    androidTestImplementation("androidx.test:rules:1.6.1")
}

Uruchamianie testów na CI

Testy Espresso można uruchamiać przez Google Android Test Orchestrator, który izoluje każdy test w osobnym procesie i czyści stan między uruchomieniami. Eliminuje to flaky-testy związane z pozostałościami danych poprzednich testów i zwiększa stabilność na serwerach CI. Do równoległego uruchamiania używa się shardingu — dystrybucji testów pomiędzy wieloma emulatorami.

Często zadawane pytania

Czym Espresso różni się od UI Automator?

Espresso działa wewnątrz procesu aplikacji i używa automatycznej synchronizacji z wątkiem UI. UI Automator działa na poziomie systemu, może współdziałać z innymi aplikacjami, ale wymaga ręcznego zarządzania oczekiwaniem.

Dlaczego Espresso nazywa się frameworkiem z „trójnogim psem“?

To metafora z prezentacji Google: test Espresso stoi na trzech nogach — ViewMatcher (wyszukiwanie), ViewAction (działanie) i ViewAssertion (sprawdzenie). Jeśli zabraknie którejkolwiek z nich, test traci stabilność, jak trójnogi pies.

Jak testować RecyclerView przez Espresso?

Do RecyclerView używa się biblioteki espresso-contrib i metod onView(withId(R.id.recycler)).perform(actionOnItemAtPosition(0, click())). Alternatywą jest onData() dla AdapterView lub niestandardowy ViewAction do wyszukiwania elementu po tekście wewnątrz RecyclerView. Dodatkowo można użyć RecyclerViewActions z espresso-contrib do przewijania do elementu i działań na nim.

Czym jest flaky-test i jak Espresso z nim walczy?

Flaky-test — test, który czasami pada bez zmiany kodu, z powodu race condition lub asynchroniczności. Espresso rozwiązuje ten problem przez Idling Resource — oczekiwanie na zakończenie wszystkich zadań tła przed wykonaniem sprawdzenia.

Czy można używać Espresso do testowania zrzutów ekranu?

Sam Espresso nie jest przeznaczony do testów zrzutów ekranu, ale można go łączyć z bibliotekami takimi jak Shot lub Paparazzi. Espresso przygotowuje UI w żądanym stanie, a biblioteka porównania wykonuje zrzut ekranu i porównuje z wzorcem. Takie podejście nazywa się wizualnym testowaniem regresji i pomaga znajdować nieoczekiwane zmiany w interfejsie.

Podsumowanie

  • Espresso — framework do testowania UI Android od Google z automatyczną synchronizacją.
  • ViewMatchers — API do wyszukiwania elementów po ID, tekście, hierarchii i kombinacjach.
  • ViewActions — click, typeText, scrollTo, swipe do interakcji z UI.
  • ViewAssertions — matches, doesNotExist do sprawdzania stanu elementów.
  • Idling Resource — synchronizacja testu z operacjami asynchronicznymi i korutynami.
  • Trzy kroki — onView().perform().check() = znajdź, wykonaj, sprawdź.
  • AndroidX Test — biblioteki do uruchamiania testów instrumentalnych na emulatorze lub urządzeniu.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również