UI-testen controleert de correcte weergave en interactie van elementen van de gebruikersinterface van een mobiele app — knoppen, tekstvelden, lijsten en navigatiecomponenten. In tegenstelling tot unittesten die de bedrijfslogica controleren, emuleren UI-tests gebruikersacties: tikken, vegen, tekstinvoer en controleren de reactie van de interface. Volgens onderzoek van Android Developers, 2024, dekt UI-testen 70% van de kritieke gebruikersscenario’s en maakt het mogelijk om lay-outfouten te vinden die niet toegankelijk zijn voor logische controles.
Belangrijkste
UI-testen is een vorm van geautomatiseerde controle waarbij de testcode interactie heeft met de grafische interface van de app, precies zoals een echte gebruiker zou doen. De test vindt een element op het scherm — knop, tekstveld, lijst — voert er een actie op uit en controleert de verwachte reactie van de interface. Bijvoorbeeld, na het invoeren van een onjuist wachtwoord controleert de UI-test of er een foutmelding met de juiste tekst op het scherm verschijnt.
Het belangrijkste verschil tussen UI-tests en andere vormen van automatisering is dat ze werken via de Accessibility-laag van het besturingssysteem, niet via de interne API’s van de app. Dit betekent dat UI-tests de interface precies zien zoals de gebruiker en het schermleessysteem. Hierdoor controleren UI-tests niet alleen de functionaliteit, maar ook de toegankelijkheid van elementen — naleving van WCAG-vereisten.
Volgens de JetBrains Developer Ecosystem 2023-enquête gebruikt 58% van de mobiele teams UI-tests in hun CI/CD-pipeline. De gemiddelde dekkingsgraad van UI-tests in commerciële projecten is 30–40% van de app-schermen. Projecten met UI-tests krijgen 25% minder negatieve beoordelingen in app-winkels gerelateerd aan interface-crashes.
Het belangrijkste verschil tussen UI-tests en unittesten is het abstractieniveau. Unittests werken met individuele klassen en functies, geïsoleerd van het Android- of iOS-framework. Ze worden uitgevoerd op de JVM (voor Android) zonder de emulator te starten en duren milliseconden. UI-tests worden uitgevoerd op een echt apparaat of emulator, werken samen met systeemdiensten en hebben seconden of minuten nodig voor één scenario.
Ook de doelgroep van de tests verschilt. UI-tests controleren end-to-end gebruikersscenario’s — registratie, bestelling plaatsen, zoeken. Unittests dekken de bedrijfslogica: berekeningen, validatie, gegevensconversie. Een UI-test controleert niet de juistheid van een belastingberekening — hij controleert of het eindbedrag op het scherm wordt weergegeven. De berekening zelf wordt gecontroleerd door een unittest.
Volgens Google Testing Blog (2020) moet de optimale verhouding van tests in een project de regel van de testpiramide volgen: 70% unittests, 20% integratietests en 10% UI-tests. Het schenden van deze verhouding ten gunste van UI-tests leidt tot langere uitvoeringstijden en breekbaarheid van de testsuite, omdat UI-tests gevoelig zijn voor wijzigingen in de schermindeling.
Voor Android is het dominante framework Espresso — een bibliotheek van Google ingebouwd in AndroidX Test. Espresso synchroniseert automatisch met de UI-thread en wacht op het voltooien van animaties en achtergrondtaken voordat de volgende controle wordt uitgevoerd. Voor Jetpack Compose wordt de Compose UI Test-extensie gebruikt, die werkt via semantische knooppunten in plaats van traditionele view-identificatoren.
Voor iOS is het belangrijkste hulpmiddel XCUITest, onderdeel van Xcode. Tests worden geschreven in Swift en gebruiken Accessibility-identificatoren om elementen te vinden. XCUITest ondersteunt het opnemen van tests via de record-functie en integratie met CI-systemen via xcodebuild. Voor cross-platform projecten wordt Appium gebruikt, gebaseerd op het WebDriver-protocol, waarmee dezelfde tests op Android en iOS kunnen worden uitgevoerd met minimale wijzigingen in de code.
Espresso werkt met het traditionele View-systeem via onView en bron-id-identificatoren. Compose UI Test gebruikt een semantische laag, waardoor tests minder afhankelijk zijn van de view-hiërarchie. Bijvoorbeeld, het vinden van een knop in Espresso: onView(withId(R.id.submit)), in Compose: onNodeWithTag(„submit”). Compose-tests verwerken automatisch recompositie en vereisen geen expliciet wachten op de inactieve toestand.
XCUITest gebruikt XCUIApplication als toegangspunt. Elk interface-element wordt gevonden via Accessibility-eigenschappen: accessibilityIdentifier voor programmatische toegang en accessibilityLabel voor VoiceOver. Het framework ondersteunt het opnemen van tests via de record-functie in Xcode — de ontwikkelaar voert acties uit op de simulator en Xcode genereert de testcode. Voltooide tests worden uitgevoerd via xcodebuild test.
Appium is gebaseerd op het WebDriver-protocol en ondersteunt elke taal: Java, Python, JavaScript. Voor het vinden van elementen worden de strategieën id, xpath, class name en accessibility id gebruikt. Appium vereist installatie van een server en configuratie van Desired Capabilities — platformName, deviceName, appPackage. Een alternatief is Maestro, dat YAML-scenario’s gebruikt en geen compilatie van testcode vereist.
Laten we UI-tests voor hetzelfde scenario — inloggen op de app — bekijken in drie verschillende frameworks: Espresso voor Android, XCUITest voor iOS en Appium voor de cross-platform benadering. Scenario: voer gebruikersnaam en wachtwoord in, druk op de inlogknop, controleer of het welkomstbericht wordt weergegeven.
De test in Espresso gebruikt onView om het element te vinden op identificator en perform om de actie uit te voeren. De check-methode met de isDisplayed-matcher bevestigt dat het element zichtbaar is op het scherm.
@RunWith(AndroidJUnit4::class)
class LoginUiTest {
@Rule
@JvmField
val composeTestRule = createComposeRule()
@Test
fun login_withValidCredentials_showsWelcome() {
composeTestRule
.onNodeWithTag("emailField")
.performTextInput("user@example.com")
composeTestRule
.onNodeWithTag("passwordField")
.performTextInput("secret123")
composeTestRule
.onNodeWithTag("loginButton")
.performClick()
composeTestRule
.onNodeWithText("Welkom, Gebruiker!")
.assertIsDisplayed()
}
}
XCUITest gebruikt XCUIApplication voor toegang tot interface-elementen via Accessibility-identificatoren. De methoden tap() en exists zorgen voor interactie en verificatie.
class LoginUITests: XCTestCase {
let app = XCUIApplication()
override func setUp() {
continueAfterFailure = false
app.launch()
}
func testLogin_withValidCredentials_showsWelcome() {
app.textFields["emailField"].tap()
app.textFields["emailField"].typeText("gebruiker@example.com")
app.secureTextFields["passwordField"].tap()
app.secureTextFields["passwordField"].typeText("geheim123")
app.buttons["loginButton"].tap()
XCTAssertTrue(app.staticTexts["Welcome, User!"].exists)
}
}
Het eerste principe — gebruik Accessibility-identificatoren in plaats van tekstlabels om elementen te vinden. De tekst van een knop kan veranderen bij lokalisatie, terwijl de identificator stabiel blijft. In Android is dit de eigenschap contentDescription, in iOS — accessibilityIdentifier. Deze benadering maakt tests onafhankelijk van de interfacetaal en verlaagt de onderhoudskosten bij wijzigingen in de copywriting.
Vermijd sleep() en vaste vertragingen — gebruik de ingebouwde wachtmechanismen van het framework. Espresso wacht automatisch op het voltooien van animaties en achtergrondtaken. XCUITest biedt XCTAssertTrue met een timeout. Expliciete pauzes vertragen tests en maken ze minder stabiel, vooral op langzame apparaten in een CI-omgeving.
Groepeer tests op kritiekheid: smoke-tests (3–5 kritieke scenario’s) worden bij elke commit uitgevoerd, de volledige set UI-tests — vóór de release. Volgens Google Testing Blog (2022) verminderen UI-tests die meer dan 30 minuten duren in CI de uitvoeringsfrequentie met 40%, wat hun effectiviteit als hulpmiddel voor vroege detectie van regressies vermindert.
UI-tests hebben een aantal beperkingen. Gevoeligheid voor lay-outwijzigingen: een wijziging van de identificator, hiërarchie of het type element breekt de test, zelfs bij ongewijzigde functionaliteit. Oplossing — gebruik van het Page Object-patroon, dat elementselectors centraliseert in aparte klassen. Bij een lay-outwijziging wordt één Page Object-bestand aangepast, niet tientallen tests.
Uitvoeringstijd: uitvoering op een echt apparaat of emulator duurt 10–50 keer langer dan een unittest. Oplossing — parallelle uitvoering van UI-tests op meerdere apparaten via Firebase Test Lab of AWS Device Farm. Instabiliteit (flakiness) — een veelvoorkomend probleem bij CI-uitvoeringen, veroorzaakt door animaties, netwerkvertragingen of de staat van de emulator. Ter bestrijding van flakiness worden automatische herkansingen van mislukte tests en stabiliteitsanalyse van elk testscenario toegepast.
Veelgestelde vragen
Voor een gemiddeld scherm zijn 3–5 UI-tests voldoende: happy path, foutvalidatie, lege toestand, orientatiewijziging en Accessibility-controle. Complexe schermen met meerdere toestanden — bestelformulieren, instellingen — kunnen 10–15 tests vereisen voor volledige dekking van de kritieke scenario’s.
Ja, Appium en Maestro maken het mogelijk dezelfde scenario’s op beide platforms uit te voeren. Native frameworks — Espresso en XCUITest — bieden echter betere stabiliteit, snelheid en toegang tot platformmogelijkheden die niet beschikbaar zijn via een WebDriver-proxy.
Voor Compose wordt de bibliotheek Compose UI Test gebruikt met semantische matchers: onNodeWithText, onNodeWithTag, onNodeWithContentDescription. De semantische laag van Compose abstraheert de view-hiërarchie, waardoor tests minder breekbaar zijn in vergelijking met traditioneel Espresso voor het View-systeem.
De basisuitvoering van UI-tests gebeurt op emulators in CI — dit is snel en goedkoop. De definitieve verificatie vóór de release wordt aanbevolen op fysieke apparaten via Firebase Test Lab om rekening te houden met de kenmerken van echte hardware: verschillende resoluties, OS-versies en prestaties.
Gebruik parallelle uitvoering op meerdere apparaten, schakel animaties op de emulator uit via Developer Options, bouw een modulaire testarchitectuur en voer de smoke-set bij elke commit uit, en de volledige regressie-uitvoering volgens schema of vóór de release.
Samenvatting
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.
Lees ook