Espresso — wat is het, werkingsprincipes en hoe te gebruiken

Auteur: IT Sectr Gepubliceerd: 2026-04-08 Leestijd: 8 min

Espresso is een framework voor geautomatiseerd UI-testen van Android-apps, ontwikkeld door het Google-team en onderdeel van AndroidX Test. In tegenstelling tot instrumentele tests die geïsoleerde componenten controleren, interageert Espresso met de echte UI: knoppen indrukken, tekst invoeren, weergave van elementen controleren. Volgens Google Android Developers biedt Espresso automatische synchronisatie met de UI-thread, waardoor handmatige Thread.sleep() overbodig wordt.

Belangrijkste punten

  • Espresso — Android UI-testframework met automatische threadsynchronisatie.
  • ViewMatcher — zoeken naar View-element op scherm op ID, tekst, ouderhiërarchie.
  • ViewAction — actie op element: klikken, tekst invoeren, swipen.
  • ViewAssertion — controle van elementstatus: wordt weergegeven, bevat tekst, is actief.
  • Idling Resource — wachtmechanisme voor voltooiing van asynchrone bewerkingen vóór UI-controle.

Wat is Espresso?

Espresso is een bibliotheek voor het schrijven van geautomatiseerde UI-tests voor Android, onderdeel van Google AndroidX Test. Het biedt een API voor het vinden van View-elementen op het scherm, het uitvoeren van acties erop (klikken, invoeren, swipen) en het controleren van hun status (wordt weergegeven, bevat tekst, is actief).

Het belangrijkste kenmerk van Espresso is automatische synchronisatie met de hoofdthread van de app. Het framework wacht op voltooiing van alle asynchrone taken (coroutines, AsyncTask, Handler) voordat het de volgende controle uitvoert. Dit elimineert flaky-tests gerelateerd aan race conditions en maakt UI-tests stabiel en betrouwbaar — geen enkele test bevat Thread.sleep() of wachtlussen.

Espresso volgt het principe van Three-Legged Dog — een test bestaat uit drie stappen: element vinden (ViewMatcher), actie uitvoeren (ViewAction), resultaat controleren (ViewAssertion). Alle drie stappen worden geschreven in een keten van aanroepen onView().perform().check(). Dit concept maakt tests voorspelbaar en gemakkelijk leesbaar — elke test beschrijft expliciet wat hij zoekt, wat hij doet en wat hij controleert.

Hoe werkt Espresso

Architectuur van Espresso is gebaseerd op drie componenten: Espresso (ingangspunt — statische methoden onView en onData), ViewMatchers (elementen zoeken), ViewActions (acties) en ViewAssertions (controles). Intern gebruikt het framework Idling Resource voor synchronisatie met de UI-thread.

Basis Espresso-test

Een eenvoudige test vindt een knop op ID, voert een klik uit en controleert of de tekst „Gereed“ verschijnt. Alle operaties worden synchroon uitgevoerd vanuit het oogpunt van de test — Espresso garandeert dat de UI-thread de gebeurtenisverwerking heeft voltooid voordat de test verdergaat. Dit wordt bereikt door een ingebouwd wachtmechanisme: onView blokkeert de testuitvoering totdat de UI stabiel is.

kotlin
@Test
fun buttonClick_showsSuccessText() {
    // Knop vinden op ID en klikken
    onView(withId(R.id.button_submit))
        .perform(click())

    // Controleren of tekst „Gereed“ wordt weergegeven
    onView(withText("Gereed"))
        .check(matches(isDisplayed()))
}

ActivityScenario-regel

Voor het starten van een Espresso-test wordt ActivityScenario (AndroidX Test) gebruikt, die een Activity in de gewenste staat maakt — gestart, gepauzeerd, vernietigd. ActivityScenario maakt het mogelijk om de levenscyclus van Activity te testen naast pure UI. Bijvoorbeeld, kan worden gecontroleerd of gegevens worden opgeslagen bij schermrotatie (recreatie van Activity) en worden hersteld na vernietiging.

ViewMatchers zijn een set methoden van de klasse Espresso.onView waarmee View op het scherm kan worden gevonden op verschillende criteria: resource-ID (R.id), tekst, hint, ouderelement en hiërarchie. Als één matcher geen uniek resultaat geeft, worden matchers gecombineerd via allOf().

MatcherDoel
withId(R.id.name)Zoeken op resource-ID
withText(„tekst“)Zoeken op weergegeven tekst
withHint(„hint“)Zoeken op hint-attribuut van EditText
isDisplayed()Controleren of element zichtbaar is op scherm
hasSibling(matcher)Zoeken op naburig element
allOf(m1, m2)Combinatie van meerdere matchers

Combinatie van matchers

Als er meerdere dezelfde elementen op het scherm zijn (bijvoorbeeld twee TextView met verschillende tekst), is het handig om matchers te combineren via allOf: onView(allOf(withId(R.id.title), withText(„Hallo“))). Dit garandeert de selectie van een uniek element. De omgekeerde operator — not() — sluit elementen uit van zoeken, en hasSibling() zoekt een element naast een bekend element.

ViewActions: interactie met UI

ViewActions zijn acties die Espresso uitvoert op de gevonden View: click(), typeText(), clearText(), scrollTo(), swipeLeft() en andere. Acties worden doorgegeven aan de methode perform() die meerdere acties achter elkaar kan accepteren.

Keten van acties

De methode perform() accepteert vararg ViewAction, wat het mogelijk maakt om een reeks acties op één element uit te voeren: veld wissen, nieuwe tekst invoeren, toetsenbord sluiten en knop indrukken. Alle acties worden uitgevoerd in de volgorde waarin ze worden vermeld, en Espresso garandeert dat de vorige actie is voltooid voordat de volgende begint.

kotlin
// Tekst invoeren in EditText en knop indrukken
onView(withId(R.id.edit_email))
    .perform(
        clearText(),
        typeText("user@example.com"),
        closeSoftKeyboard()
    )

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

Controle via onData

Voor elementen in AdapterView (ListView, RecyclerView) wordt de methode onData() gebruikt in plaats van onView. Het werkt met adaptergegevens, niet met View — vindt het element op inhoud van het model en retourneert de corresponderende View voor verdere acties. onData gebruikt hamcrest-matchers om het element te vinden op velden van het gegevensmodel.

ViewAssertions: status controleren

ViewAssertions controleren of View in een bepaalde status verkeert. De basismethode — matches(matcher) — controleert of het element voldoet aan de opgegeven matcher. Aanvullend biedt Espresso doesNotExist() (element bestaat niet) en selectedDescendantsMatch() (controle van geneste elementen).

Standaardcontroles

De meest voorkomende controles in UI-tests: element wordt weergegeven (isDisplayed), element bevat bepaalde tekst (withText), element is actief (isEnabled), element is niet geselecteerd (isNotChecked). Elke controle gooit een gedetailleerde uitzondering bij mislukking — met vermelding van de View-hiërarchie op het scherm. Dit vereenvoudigt het debuggen: in het foutbericht is te zien welke elementen daadwerkelijk op het scherm stonden op het moment van controle.

Aangepaste ViewAssertions

Als standaardcontroles niet voldoende zijn, kan een eigen controle worden gemaakt via de interface ViewAssertion. Een aangepaste assertion ontvangt View en kan de status ervan programmatisch controleren — bijvoorbeeld tekstkleur, marges of status van een aangepast component dat niet via standaard matchers wordt blootgelegd.

kotlin
// Controle: TextView wordt weergegeven en bevat tekst
onView(withId(R.id.text_welcome))
    .check(matches(isDisplayed()))
    .check(matches(withText("Welkom")))

// Controle: element wordt NIET weergegeven
onView(withId(R.id.progress_bar))
    .check(doesNotExist())

Idling Resources voor asynchrone bewerkingen

Idling Resource is het mechanisme van Espresso voor het synchroniseren van de test met asynchrone bewerkingen. Standaard wacht Espresso op voltooiing van Handler, AsyncTask en coroutines (via coroutinesIdlingResource). Als de app achtergrondwerk uitvoert via eigen threads of callback-services, moet een aangepaste Idling Resource worden geregistreerd.

Voorbeeld met coroutines

Vanaf AndroidX Test 1.4.0 ondersteunt Espresso coroutines via CoroutinesIdlingResource. De test wacht automatisch op voltooiing van alle gestarte coroutines voordat UI-controles worden uitgevoerd. Voor complexere scenario’s wordt CountingIdlingResource gebruikt — een teller die wordt verhoogd bij starten van een taak en verlaagd bij voltooiing.

kotlin
// IdlingResource registreren voor 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
    }
}

Espresso instellen in Android-project

Aansluiten van Espresso in een Android-project gebeurt door afhankelijkheden toe te voegen in build.gradle op moduleniveau. Espresso maakt deel uit van AndroidX Test, dus het is voldoende om afhankelijkheden op te geven voor Espresso-core, extensies en JUnit-integratie. Tests worden geplaatst in de map src/androidTest en uitgevoerd op een fysiek apparaat of emulator via AndroidJUnitRunner.

Gradle-configuratie

De minimale set afhankelijkheden omvat espresso-core (kern), espresso-contrib (extra matchers voor RecyclerView, Drawer, Picker) en runner (AndroidX-testrunner). Alle tests worden uitgevoerd op emulator of fysiek apparaat via Android Test Orchestrator.

kotlin
// build.gradle.kts (androidTest dependencies)
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")
}

Tests uitvoeren op CI

Espresso-tests kunnen worden uitgevoerd via Google Android Test Orchestrator, die elke test isoleert in een apart proces en de status opschoont tussen uitvoeringen. Dit elimineert flaky-tests gerelateerd aan achtergebleven gegevens van vorige tests en verhoogt de stabiliteit op CI-servers. Voor parallelle uitvoering wordt sharding gebruikt — verdeling van tests over meerdere emulators.

Veelgestelde vragen

Waarin verschilt Espresso van UI Automator?

Espresso werkt binnen het proces van de app en gebruikt automatische synchronisatie met de UI-thread. UI Automator werkt op systeemniveau, kan interageren met andere apps, maar vereist handmatig wachtbeheer.

Waarom wordt Espresso het „driepotige hond“-framework genoemd?

Dit is een metafoor uit een Google-presentatie: de Espresso-test staat op drie pijlers — ViewMatcher (zoeken), ViewAction(actie) en ViewAssertion(controle). Als een ervan wordt verwijderd, verliest de test stabiliteit, als een driepotige hond.

Hoe test je RecyclerView met Espresso?

Voor RecyclerView wordt de bibliotheek espresso-contrib gebruikt met methoden onView(withId(R.id.recycler)).perform(actionOnItemAtPosition(0, click())). Alternatief — onData() voor AdapterView of een aangepaste ViewAction voor het zoeken van een element op tekst in RecyclerView. Aanvullend kan RecyclerViewActions uit espresso-contrib worden gebruikt voor scrollen naar een element en acties erop.

Wat is een flaky-test en hoe bestrijdt Espresso het?

Flaky-test is een test die soms faalt zonder codewijzigingen, door race conditions of asynchroniciteit. Espresso lost dit probleem op via Idling Resource — wachten op voltooiing van alle achtergrondtaken voordat de controle wordt uitgevoerd.

Kan Espresso worden gebruikt voor screenshot-testen?

Espresso zelf is niet bedoeld voor screenshot-tests, maar kan worden gecombineerd met bibliotheken zoals Shot of Paparazzi. Espresso bereidt de UI voor in de gewenste staat, de vergelijkingsbibliotheek maakt een screenshot en vergelijkt deze met een referentie. Deze aanpak wordt visuele regressietests genoemd en helpt bij het vinden van onverwachte veranderingen in de interface.

Samenvatting

  • Espresso — Android UI-testframework van Google met automatische synchronisatie.
  • ViewMatchers — API voor het zoeken van elementen op ID, tekst, hiërarchie en combinaties.
  • ViewActions — click, typeText, scrollTo, swipe voor interactie met UI.
  • ViewAssertions — matches, doesNotExist voor controleren van elementstatus.
  • Idling Resource — synchronisatie van test met asynchrone bewerkingen en coroutines.
  • Drie stappen — onView().perform().check() = vinden, doen, controleren.
  • AndroidX Test — bibliotheken voor uitvoeren van instrumentele tests op emulator of apparaat.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook