Az Espresso egy keretrendszer Android-alkalmazások automatizált UI-teszteléséhez, amelyet a Google csapata fejlesztett és az AndroidX Test része. Ellentétben az izolált összetevőket vizsgáló instrumentális tesztekkel, az Espresso a valódi UI-val lép kölcsönhatásba: gombokat nyom meg, szöveget ír be, elemek megjelenését ellenőrzi. A Google Android Developers szerint az Espresso automatikus szinkronizálást biztosít az UI-szállal, ami kiküszöböli a kézi Thread.sleep() szükségességét.
Főbb pontok
Az Espresso egy könyvtár automatizált UI-tesztek írásához Androidhoz, amely a Google AndroidX Test része. API-t biztosít View-elemek képernyőn történő megkereséséhez, rajtuk műveletek végrehajtásához (kattintás, bevitel, csúszás) és állapotuk ellenőrzéséhez (megjelenik, tartalmaz szöveget, aktív).
Az Espresso fő jellemzője az automatikus szinkronizálás az alkalmazás fő szálával. A keretrendszer megvárja az összes aszinkron feladat (korutinok, AsyncTask, Handler) befejeződését a következő ellenőrzés végrehajtása előtt. Ez kiküszöböli a versenyhelyzetekkel kapcsolatos ingatag teszteket, és stabillá és megbízhatóvá teszi az UI-teszteket — egyetlen teszt sem tartalmaz Thread.sleep()-et vagy várakozó ciklusokat.
Az Espresso a Three-Legged Dog elvet követi — egy teszt három lépésből áll: elem megkeresése (ViewMatcher), művelet végrehajtása (ViewAction), eredmény ellenőrzése (ViewAssertion). Mindhárom lépést egy onView().perform().check() hívásláncba írjuk. Ez a koncepció kiszámíthatóvá és könnyen olvashatóvá teszi a teszteket — minden teszt egyértelműen leírja, mit keres, mit csinál és mit ellenőriz.
Az Espresso architektúrája három összetevőn alapul: Espresso (belépési pont — onView és onData statikus metódusok), ViewMatchers (elemek keresése), ViewActions (műveletek) és ViewAssertions (ellenőrzések). Belül a keretrendszer Idling Resource-ot használ az UI-szállal való szinkronizáláshoz.
Egy egyszerű teszt megkeres egy gombot ID alapján, végrehajt egy kattintást és ellenőrzi, hogy megjelent-e a „Kész” szöveg. Minden művelet szinkron módon történik a teszt szempontjából — az Espresso garantálja, hogy az UI-szál befejezte az esemény feldolgozását, mielőtt a teszt folytatódna. Ezt egy beépített várakozási mechanizmus éri el: az onView blokkolja a teszt végrehajtását, amíg az UI stabil nem lesz.
@Test
fun buttonClick_showsSuccessText() {
// Gomb megkeresése ID alapján és kattintás
onView(withId(R.id.button_submit))
.perform(click())
// Annak ellenőrzése, hogy a „Kész” szöveg megjelenik
onView(withText("Kész"))
.check(matches(isDisplayed()))
}
Az Espresso teszt elindításához ActivityScenario-t (AndroidX Test) használunk, amely a kívánt állapotban hozza létre az Activity-t — futó, felfüggesztett, megsemmisített. Az ActivityScenario lehetővé teszi az Activity életciklusának tesztelését a tiszta UI mellett. Például ellenőrizhető, hogy az adatok mentésre kerülnek-e képernyőelforgatáskor (Activity újralétrehozása) és visszaállítódnak-e a megsemmisítés után.
A ViewMatchers az Espresso.onView osztály metódusainak halmaza, amelyek lehetővé teszik a View megkeresését a képernyőn különböző kritériumok alapján: erőforrás-azonosító (R.id), szöveg, hintsúgó, szülőelem és hierarchia. Ha egyetlen matcher nem ad egyedi eredményt, a matcherek allOf() segítségével kombinálhatók.
| Matcher | Cél |
|---|---|
| withId(R.id.name) | Keresés erőforrás ID alapján |
| withText(„szöveg“) | Keresés megjelenített szöveg alapján |
| withHint(„súgó“) | Keresés EditText hint attribútuma alapján |
| isDisplayed() | Annak ellenőrzése, hogy az elem látható-e a képernyőn |
| hasSibling(matcher) | Keresés szomszédos elem alapján |
| allOf(m1, m2) | Több matcher kombinációja |
Ha több azonos elem van a képernyőn (például két különböző szövegű TextView), a matchereket célszerű allOf-fal kombinálni: onView(allOf(withId(R.id.title), withText(„Szia“))). Ez garantálja az egyetlen elem kiválasztását. A fordított operátor — not() — kizárja az elemeket a keresésből, a hasSibling() pedig egy ismert elem melletti elemet keres.
A ViewActions olyan műveletek, amelyeket az Espresso hajt végre a megtalált View-n: click(), typeText(), clearText(), scrollTo(), swipeLeft() és mások. A műveletek a perform() metódusnak kerülnek átadásra, amely egymás után több műveletet is elfogadhat.
A perform() metódus vararg ViewAction-t fogad el, ami lehetővé teszi műveletek sorozatának végrehajtását egyetlen elemen: mező törlése, új szöveg beírása, billentyűzet bezárása és gomb megnyomása. Minden művelet a felsorolás sorrendjében történik, és az Espresso garantálja, hogy az előző művelet befejeződött a következő megkezdése előtt.
// Szöveg beírása EditText-be és gomb megnyomása
onView(withId(R.id.edit_email))
.perform(
clearText(),
typeText("user@example.com"),
closeSoftKeyboard()
)
onView(withId(R.id.button_login))
.perform(click())
Az AdapterView-ban (ListView, RecyclerView) lévő elemekhez onView helyett a onData() metódust használjuk. Ez az adapter adataival dolgozik, nem a View-val — a modell tartalma alapján találja meg az elemet és adja vissza a megfelelő View-t a további műveletekhez. Az onData hamcrest-matchereket használ az elem adatmodell mezői alapján történő megkereséséhez.
A ViewAssertions ellenőrzi, hogy a View egy adott állapotban van-e. Az alapmetódus — matches(matcher) — ellenőrzi, hogy az elem megfelel-e a megadott matchernek. Ezenkívül az Espresso kínálja a doesNotExist() (elem nem létezik) és a selectedDescendantsMatch() (beágyazott elemek ellenőrzése) metódusokat.
A leggyakoribb ellenőrzések UI-tesztekben: elem megjelenik (isDisplayed), elem tartalmaz egy adott szöveget (withText), elem aktív (isEnabled), elem nincs kiválasztva (isNotChecked). Minden ellenőrzés részletes kivételt dob sikertelenség esetén — a képernyőn lévő View-hierarchia feltüntetésével. Ez leegyszerűsíti a hibakeresést: a hibaüzenetből látszik, hogy mely elemek voltak ténylegesen a képernyőn az ellenőrzés pillanatában.
Ha a szabványos ellenőrzések nem elegendőek, sajátot lehet létrehozni a ViewAssertion interfész segítségével. Az egyedi assertion megkapja a View-t és programozottan ellenőrizheti annak állapotát — például szövegszínt, margókat vagy egy egyedi komponens állapotát, amely nem érhető el a szabványos matchereken keresztül.
// Ellenőrzés: TextView megjelenik és tartalmaz szöveget
onView(withId(R.id.text_welcome))
.check(matches(isDisplayed()))
.check(matches(withText("Üdvözöljük")))
// Ellenőrzés: elem NEM jelenik meg
onView(withId(R.id.progress_bar))
.check(doesNotExist())
Az Idling Resource az Espresso mechanizmusa a teszt aszinkron műveletekkel való szinkronizálásához. Alapértelmezésben az Espresso megvárja a Handler, AsyncTask és korutinok (a coroutinesIdlingResource segítségével) befejeződését. Ha az alkalmazás saját szálakon vagy Callback-szolgáltatásokon keresztül végez háttérmunkát, egyedi Idling Resource-ot kell regisztrálni.
Az AndroidX Test 1.4.0-tól kezdve az Espresso támogatja a korutinokat a CoroutinesIdlingResource segítségével. A teszt automatikusan megvárja az összes elindított korutin befejeződését, mielőtt UI-ellenőrzéseket végez. Összetettebb forgatókönyvekhez a CountingIdlingResource-ot használjuk — egy számlálót, amely a feladat indításakor nő és befejeződésekor csökken.
// IdlingResource regisztrálása OkHttp számára
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
}
}
Csatlakoztatás Az Espresso csatlakoztatása Android-projektben a függőségek hozzáadásával történik a modul szintű build.gradle fájlban. Az Espresso az AndroidX Test része, ezért elegendő megadni a függőségeket az Espresso magjához, kiterjesztéseihez és JUnit-integrációjához. A tesztek a src/androidTest könyvtárba kerülnek és fizikai eszközön vagy emulátoron futnak az AndroidJUnitRunner segítségével.
A minimális függőségkészlet tartalmazza a espresso-core-t (mag), espresso-contrib-ot (további matcherek RecyclerView-hoz, Drawer-hez, Picker-hez) és a runner-t (AndroidX tesztfuttató). Az összes teszt emulátoron vagy fizikai eszközön fut az Android Test Orchestrator segítségével.
// 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")
}
Az Espresso tesztek futtathatók a Google Android Test Orchestrator segítségével, amely minden tesztet külön folyamatban izolál és megtisztítja az állapotot a futtatások között. Ez kiküszöböli az előző tesztek maradványadataihoz kapcsolódó ingatag teszteket és növeli a stabilitást CI-szervereken. Párhuzamos futtatáshoz sharding-ot használunk — a tesztek elosztását több emulátor között.
Gyakran Ismételt Kérdések
Az Espresso az alkalmazás folyamatán belül működik és automatikus szinkronizálást használ az UI-szállal. Az UI Automator rendszer szintjén működik, kölcsönhatásba léphet más alkalmazásokkal, de kézi várakozáskezelést igényel.
Ez egy metafora a Google prezentációjából: az Espresso teszt három pilléren nyugszik — ViewMatcher (keresés), ViewAction (művelet) és ViewAssertion (ellenőrzés). Ha bármelyiket eltávolítjuk, a teszt elveszti stabilitását, mint egy háromlábú kutya.
A RecyclerView-hoz az espresso-contrib könyvtárat és az onView(withId(R.id.recycler)).perform(actionOnItemAtPosition(0, click())) metódusokat használjuk. Alternatíva — onData() AdapterView-hoz vagy egyedi ViewAction az elem szöveg alapján történő kereséséhez RecyclerView-ban. Ezenkívül használható a RecyclerViewActions az espresso-contrib-ból az elemhez görgetéshez és azon végrehajtott műveletekhez.
Az ingatag teszt olyan teszt, amely néha kód változtatása nélkül meghiúsul, versenyhelyzetek vagy aszinkronitás miatt. Az Espresso ezt a problémát az Idling Resource segítségével oldja meg — megvárja az összes háttérfeladat befejeződését az ellenőrzés végrehajtása előtt.
Magát az Espresso-t nem képernyőkép-tesztekre tervezték, de kombinálható olyan könyvtárakkal, mint a Shot vagy a Paparazzi. Az Espresso előkészíti az UI-t a kívánt állapotba, az összehasonlító könyvtár pedig képernyőképet készít és összehasonlítja a referenciával. Ezt a megközelítést vizuális regressziós tesztelésnek nevezik és segít megtalálni a váratlan változásokat a felületen.
Összefoglaló
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is