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. Наприклад, можна перевірити, що дані зберігаються при повороті екрану (recreation Activity) та відновлюються після знищення.

ViewMatchers — це набір методів із класу Espresso.onView, які дозволяють знайти View на екрані за різними критеріями: ідентифікатором ресурсу (R.id), текстом, hint-підказкою, батьківським елементом та ієрархією. Якщо один матчер не дає унікального результату, матчери комбінуються через allOf().

МатчерПризначення
withId(R.id.name)Пошук за ID ресурсу
withText(«текст»)Пошук за текстом, що відображається
withHint(«підказка»)Пошук за hint-атрибутом EditText
isDisplayed()Перевірка, що елемент видимий на екрані
hasSibling(matcher)Пошук за сусіднім елементом
allOf(m1, m2)Комбінація декількох матчерів

Комбінація матчерів

Якщо на екрані декілька однакових елементів (наприклад, два TextView з різним текстом), зручно комбінувати матчери через 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-матчери для пошуку елемента за полями моделі даних.

ViewAssertions: перевірка стану

ViewAssertions перевіряють, що View знаходиться в певному стані. Базовий метод — matches(matcher) — перевіряє, що елемент відповідає заданому матчеру. Додатково Espresso пропонує doesNotExist() (елемент відсутній) та selectedDescendantsMatch() (перевірка вкладених елементів).

Типові перевірки

Найбільш часті перевірки в UI-тестах: елемент відображається (isDisplayed), елемент містить певний текст (withText), елемент активний (isEnabled), елемент не вибраний (isNotChecked). Кожна перевірка викидає докладний виняток у разі невдачі — із зазначенням ієрархії View на екрані. Це спрощує налагодження: у повідомленні про помилку видно, які елементи реально були на екрані в момент перевірки.

Кастомні ViewAssertions

Якщо стандартних перевірок недостатньо, можна створити власну через інтерфейс ViewAssertion. Кастомний assertion отримує View та може перевірити його стан програмно — наприклад, колір тексту, відступи або стан кастомного компонента, не розкритого через стандартні матчери.

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 (додаткові матчери для RecyclerView, Drawer, Picker) та runner (тестовий раннер AndroidX). Всі тести запускаються на емуляторі або фізичному пристрої через Android Test Orchestrator.

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

Запуск тестів на 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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також