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 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 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

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