Espresso — шта је то, принципи рада и како користити

Аутор: IT Sectr Објављено: 2026-04-08 Време читања: 8 мин

Espresso је оквир за аутоматизовано UI тестирање Android апликација, развијен од стране Google тима и део AndroidX Test-а. За разлику од инструменталних тестова који проверавају изоловане компоненте, Espresso интерагује са стварним UI-јем: притиска дугмад, уноси текст, проверава приказ елемената. Према Google Android Developers, Espresso обезбеђује аутоматску синхронизацију са UI током, што елиминише потребу за ручним Thread.sleep().

Главно

  • Espresso — оквир за UI тестирање Android-а са аутоматском синхронизацијом токова.
  • ViewMatcher — претрага View елемента на екрану по ID-у, тексту, родитељској хијерархији.
  • ViewAction — акција над елементом: клик, унос текста, свајп.
  • ViewAssertion — провера стања елемента: приказује се, садржи текст, активан је.
  • Idling Resource — механизам чекања завршетка асинхроних операција пре провере UI-ја.

Шта је Espresso?

Espresso је библиотека за писање аутоматизованих UI тестова за Android, која је део Google AndroidX Test-а. Она пружа API за проналажење View елемената на екрану, извршавање акција над њима (клик, унос, свајп) и проверу њиховог стања (приказује се, садржи текст, активан је).

Кључна карактеристика Espresso-а је аутоматска синхронизација са главним током апликације. Оквир чека завршетак свих асинхроних задатака (корутине, AsyncTask, Handler) пре него што изврши следећу проверу. Ово елиминише flaky тестове повезане са race condition-ом и чини UI тестове стабилним и поузданим — ниједан тест не садржи Thread.sleep() или петље чекања.

Espresso следи принцип Three-Legged Dog — тест се састоји од три корака: пронаћи елемент (ViewMatcher), извршити акцију (ViewAction), проверити резултат (ViewAssertion). Сва три корака се записују у ланац позива onView().perform().check(). Овај концепт чини тестове предвидљивим и лако читљивим — сваки тест јасно описује шта тражи, шта ради и шта проверава.

Како ради Espresso

Архитектура Espresso-а се заснива на три компоненте: Espresso (улозна тачка — статички методи onView и onData), ViewMatchers (претрага елемената), ViewActions (акције) и ViewAssertions (провере). Унутра, оквир користи Idling Resource за синхронизацију са UI током.

Основни Espresso тест

Најједноставнији тест проналази дугме по ID-у, извршава клик и проверава да се појавио текст „Готово“. Све операције се извршавају синхроно са становишта теста — Espresso гарантује да је UI ток завршио обраду догађаја пре него што тест настави извршење. Ово се постиже уграђеним механизмом чекања: onView блокира извршење теста док UI не постане стабилан.

kotlin
@Test
fun buttonClick_showsSuccessText() {
    // Пронаћи дугме по ID-у и кликнути
    onView(withId(R.id.button_submit))
        .perform(click())

    // Проверити да се текст „Готово“ приказује
    onView(withText("Готово"))
        .check(matches(isDisplayed()))
}

Правило ActivityScenario

За покретање Espresso теста користи се ActivityScenario (AndroidX Test) који креира Activity у жељеном стању — покренута, суспендована, уништена. ActivityScenario омогућава тестирање животног циклуса Activity-ја поред чистог UI-ја. На пример, може се проверити да се подаци чувају при ротацији екрана (рекреација Activity-ја) и враћају након уништења.

ViewMatchers су скуп метода из класе Espresso.onView који омогућавају проналажење View-а на екрану по различитим критеријумима: идентификатору ресурса (R.id), тексту, hint-упутству, родитељском елементу и хијерархији. Ако један matcher не даје јединствен резултат, matcher-и се комбинују кроз allOf().

MatcherНамена
withId(R.id.name)Претрага по ID-у ресурса
withText(„текст“)Претрага по приказаном тексту
withHint(„упутство“)Претрага по hint атрибуту EditText-а
isDisplayed()Провера да ли је елемент видљив на екрану
hasSibling(matcher)Претрага по суседном елементу
allOf(m1, m2)Комбинација више matcher-а

Комбинација matcher-а

Ако на екрану постоји више истих елемената (на пример, два TextView-а са различитим текстом), згодно је комбиновати matcher-е кроз allOf: onView(allOf(withId(R.id.title), withText(„Здраво“))). Ово гарантује избор јединственог елемента. Обрнути оператор — not() — искључује елементе из претраге, а hasSibling() тражи елемент поред познатог.

ViewActions: интеракција са UI-јем

ViewActions су акције које Espresso извршава над пронађеним View-ом: click(), typeText(), clearText(), scrollTo(), swipeLeft() и друге. Акције се прослеђују методи perform() која може прихватити више акција у низу.

Ланац акција

Метод perform() прихвата vararg ViewAction, што омогућава извршавање низа акција над једним елементом: очистити поље, унети нови текст, затворити тастатуру и кликнути дугме. Све акције се извршавају редом којим су наведене, а Espresso гарантује да је претходна акција завршена пре почетка следеће.

kotlin
// Унос текста у EditText и клик на дугме
onView(withId(R.id.edit_email))
    .perform(
        clearText(),
        typeText("user@example.com"),
        closeSoftKeyboard()
    )

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

Провера кроз onData

За елементе унутар AdapterView-а (ListView, RecyclerView) користи се метод onData() уместо onView. Он ради са подацима адаптера, а не са View-ом — проналази елемент по садржају модела и враћа одговарајући View за даље акције. onData користи hamcrest matcher-е за проналажење елемента по пољима модела података.

ViewAssertions: провера стања

ViewAssertions проверавају да ли се View налази у одређеном стању. Основни метод — matches(matcher) — проверава да ли елемент одговара задатом matcher-у. Додатно, Espresso нуди doesNotExist() (елемент не постоји) и selectedDescendantsMatch() (провера угњежђених елемената).

Типичне провере

Најчешће провере у UI тестовима: елемент се приказује (isDisplayed), елемент садржи одређени текст (withText), елемент је активан (isEnabled), елемент није изабран (isNotChecked). Свака провера баца детаљан изузетак у случају неуспеха — са навођењем хијерархије View-а на екрану. Ово поједностављује отклањање грешака: у поруци о грешци се види који су елементи стварно били на екрану у тренутку провере.

Прилагођени ViewAssertions

Ако стандардне провере нису довољне, може се креирати сопствена преко интерфејса ViewAssertion. Прилагођени assertion прима View и може проверити његово стање програмски — на пример, боју текста, маргине или стање прилагођене компоненте која није изложена кроз стандардне matcher-е.

kotlin
// Провера: TextView се приказује и садржи текст
onView(withId(R.id.text_welcome))
    .check(matches(isDisplayed()))
    .check(matches(withText("Добродошли")))

// Провера: елемент се НЕ приказује
onView(withId(R.id.progress_bar))
    .check(doesNotExist())

Idling Resources за асинхроне операције

Idling Resource је механизам Espresso-а за синхронизацију теста са асинхроним операцијама. Подразумевано, Espresso чека завршетак Handler-а, AsyncTask-а и корутина (кроз coroutinesIdlingResource). Ако апликација обавља позадински рад кроз сопствене токове или Callback сервисе, потребно је регистровати прилагођени Idling Resource.

Пример са корутинама

Од AndroidX Test 1.4.0, Espresso подржава корутине кроз CoroutinesIdlingResource. Тест аутоматски чека завршетак свих покренутих корутина пре него што изврши провере UI-ја. За сложеније сценарије користе се CountingIdlingResource — бројач који се увећава при покретању задатка и смањује при завршетку.

kotlin
// Регистрација IdlingResource за 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-а у Android пројекту

Повезивање Espresso-а у Android пројекту се врши додавањем зависности у build.gradle нивоа модула. Espresso је део AndroidX Test-а, па је довољно навести зависности за језгро Espresso-а, проширења и JUnit интеграцију. Тестови се смештају у директоријум src/androidTest и покрећу на физичком уређају или емулатору преко AndroidJUnitRunner-а.

Gradle конфигурација

Минимални скуп зависности укључује espresso-core (језгро), espresso-contrib (додатни matcher-и за RecyclerView, Drawer, Picker) и runner (тестни раннер AndroidX). Сви тестови се покрећу на емулатору или физичком уређају кроз 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")
}

Покретање тестова на CI-ју

Espresso тестови се могу покретати кроз Google Android Test Orchestrator, који изолује сваки тест у посебан процес и чисти стање између покретања. Ово елиминише flaky тестове повезане са преосталим подацима претходних тестова и повећава стабилност на CI серверима. За паралелно покретање користи се sharding — расподела тестова између више емулатора.

Често постављана питања

По чему се Espresso разликује од UI Automator-а?

Espresso ради унутар процеса апликације и користи аутоматску синхронизацију са UI током. UI Automator ради на нивоу система, може интераговати са туђим апликацијама, али захтева ручно управљање чекањем.

Зашто Espresso називају оквиром са „треногом псом“?

Ово је метафора из Google презентације: тест Espresso стоји на три ослонца — ViewMatcher (претрага), ViewAction(акција) и ViewAssertion(провера). Ако се уклони било који од њих, тест губи стабилност, попут треногог пса.

Како тестирати RecyclerView кроз Espresso?

За RecyclerView се користи библиотека espresso-contrib и методе onView(withId(R.id.recycler)).perform(actionOnItemAtPosition(0, click())). Алтернатива — onData() за AdapterView или прилагођени ViewAction за претрагу елемента по тексту унутар RecyclerView-а. Додатно се може користити RecyclerViewActions из espresso-contrib-а за скроловање до елемента и акције над њим.

Шта је flaky тест и како се Espresso бори против њега?

Flaky тест је тест који понекад пада без промене кода, због race condition-а или асинхроности. Espresso решава овај проблем кроз Idling Resource — чекање завршетка свих позадинских задатака пре извршења провере.

Може ли се Espresso користити за скриншот тестирање?

Сам Espresso није намењен за скриншот тестове, али се може комбиновати са библиотекама попут Shot или Paparazzi. Espresso припрема UI у жељено стање, а библиотека за поређење прави скриншот и упоређује га са референцом. Овај приступ се назива визуелно регресионо тестирање и помаже у проналажењу неочекиваних промена у интерфејсу.

Завршне напомене

  • Espresso — оквир за UI тестирање Android-а од Google-а са аутоматском синхронизацијом.
  • ViewMatchers — API за претрагу елемената по ID-у, тексту, хијерархији и комбинацијама.
  • ViewActions — click, typeText, scrollTo, swipe за интеракцију са UI-јем.
  • ViewAssertions — matches, doesNotExist за проверу стања елемената.
  • Idling Resource — синхронизација теста са асинхроним операцијама и корутинама.
  • Три корака — onView().perform().check() = пронађи, уради, провери.
  • AndroidX Test — библиотеке за покретање инструменталних тестова на емулатору или уређају.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође