UI-тесты Android на Espresso: разработка, стабильность, CI

Разработка UI-тестов для Android-приложения (Espresso) Вы написали экран логина на Compose, настроили Hilt, добавили Retrofit. Запускаете тест — он падает. Почему? UI-тесты на Android часто flaky — корень почти всегда в игнорировании IdlingResource. Разработчики вставляют `Thread.sleep(2000)` и н

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
UI-тесты Android на Espresso: разработка, стабильность, CI
Средний
~3-5 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    1003
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    597

Разработка UI-тестов для Android-приложения (Espresso)

Вы написали экран логина на Compose, настроили Hilt, добавили Retrofit. Запускаете тест — он падает. Почему? UI-тесты на Android часто flaky — корень почти всегда в игнорировании IdlingResource. Разработчики вставляют Thread.sleep(2000) и надеются, что пройдёт — это путь к хаосу. Без правильно настроенных IdlingResource стабильность редко превышает 60%. Тест-сьют на 100+ тестов требует 2–3 часа на прогон, половина падает из-за тайминга.

Мы предлагаем разработку UI-тестов на Espresso под ключ. Спроектируем архитектуру с паттерном Robot, настроим IdlingResource для всех асинхронных операций, интегрируем с Firebase Test Lab. За 3–5 дней получаете стабильный набор critical user flows (логин, оплата, основной UX). Один из наших проектов — приложение интернет-банка с 1200 тестами — достиг стабильности 98.5% после настройки IdlingResource.

Google официально рекомендует использовать IdlingResource для синхронизации тестов с фоновыми задачами — это основа стабильного автотестирования.

Основы и критичные нюансы

Базовая структура теста Espresso: onView(matcher).perform(action).check(assertion).

@Test fun loginWithValidCredentials_navigatesToHome() { onView(withId(R.id.emailInput)) .perform(typeText("[email protected]"), closeSoftKeyboard()) onView(withId(R.id.passwordInput)) .perform(typeText("password123"), closeSoftKeyboard()) onView(withId(R.id.loginButton)) .perform(click()) onView(withId(R.id.homeTitle)) .check(matches(isDisplayed())) } 

Самая частая причина нестабильных тестов — IdlingResource. Если приложение делает асинхронный запрос (Retrofit, Coroutine), Espresso не знает об этом и пытается найти следующий элемент до завершения операции. Решение — зарегистрировать IdlingResource.

// Для OkHttp/Retrofit используйте OkHttpIdlingResource val idlingResource = OkHttpIdlingResource.create("okhttp", okHttpClient) IdlingRegistry.getInstance().register(idlingResource) // Для корутин используйте EspressoIdlingResource IdlingRegistry.getInstance().register(EspressoIdlingResource.getIdlingResource()) 

Espresso работает в 2–3 раза быстрее UIAutomator за счёт отсутствия sleep.

Почему тесты на Espresso падают?

Помимо IdlingResource, частая проблема — race conditions при работе с RecyclerView или многопоточностью. Используйте IdlingResource для асинхронных операций и CountingIdlingResource для фоновых задач. Наш опыт: после внедрения IdlingResource стабильность тестов вырастает с 60% до 95%.

Проблема Решение
Асинхронные запросы (Retrofit, Coroutine) OkHttpIdlingResource / EspressoIdlingResource
Загрузка изображений (Glide, Coil) GlideIdlingResource
Анимации (Transition, Lottie) Отключить анимации в тестах
RecyclerView с подгрузкой CountingIdlingResource

Jetpack Compose UI testing

Если проект использует Compose, Espresso-подход заменяется на ComposeTestRule:

@get:Rule val composeTestRule = createAndroidComposeRule<MainActivity>() @Test fun loginScreen_showsErrorOnInvalidEmail() { composeTestRule.onNodeWithTag("emailInput") .performTextInput("invalid-email") composeTestRule.onNodeWithTag("loginButton") .performClick() composeTestRule.onNodeWithText("Неверный формат email") .assertIsDisplayed() } 

testTag в Compose — аналог accessibilityIdentifier в iOS. Обязательно проставляем на все тестируемые элементы через Modifier.testTag("loginButton").

Как ускорить написание тестов?

Используем Robot pattern — аналог Page Object для Compose. Он делает тесты читаемыми как сценарии и упрощает рефакторинг. Сравнение:

Критерий Robot pattern Page Object
Синтаксис Цепочки вызовов (Builder) Методы без возврата объекта
Читаемость Высокая, похожа на шаги тест-кейса Средняя, требуется дополнительная структура
Переиспользование Через композицию роботов Через наследование page-классов
Поддержка Compose Нативная, без лишних обёрток Требуется адаптация

Robot pattern подходит для Compose-проектов лучше. Пример:

class LoginRobot(private val composeTestRule: AndroidComposeTestRule<*, *>) { fun enterEmail(email: String) = apply { composeTestRule.onNodeWithTag("emailInput").performTextInput(email) } fun enterPassword(password: String) = apply { composeTestRule.onNodeWithTag("passwordInput").performTextInput(password) } fun clickLogin() = apply { composeTestRule.onNodeWithTag("loginButton").performClick() } fun assertHomeVisible() { composeTestRule.onNodeWithTag("homeScreen").assertIsDisplayed() } } // Тест читается как сценарий @Test fun validLogin_showsHome() { LoginRobot(composeTestRule) .enterEmail("[email protected]") .enterPassword("pass123") .clickLogin() .assertHomeVisible() } 

Hilt и DI в инструментальных тестах

Если проект использует Hilt, тесты требуют HiltAndroidRule. Аннотация @BindValue позволяет подменить реальный репозиторий на фейковый без изменения основного кода — тест не зависит от сети или базы данных.

Как написать стабильный тест на Espresso за 5 шагов

  1. Определите сценарий и выделите асинхронные операции.
  2. Зарегистрируйте IdlingResource для каждой операции.
  3. Используйте Robot pattern для структурирования.
  4. Запустите тест локально, проверьте стабильность.
  5. Интегрируйте с CI и Firebase Test Lab.

CI: Firebase Test Lab

Локальный эмулятор достаточен для разработки, но перед релизом — Firebase Test Lab с реальными устройствами. Пример workflow (GitHub Actions):

- name: Run Espresso tests on Firebase Test Lab run: | gcloud firebase test android run \ --type instrumentation \ --app app/build/outputs/apk/debug/app-debug.apk \ --test app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk \ --device model=Pixel8,version=34 \ --device model=GalaxyS23,version=33 

Результаты — Logcat, скриншоты при падении, видео прогона — сохраняются в Google Cloud Storage. Настройка CI входит в объём работ.

Что входит в разработку UI-тестов на Espresso

  • Проектирование архитектуры тестов (выбор паттерна, настройка IdlingResource)
  • Написание critical user flows (логин, оплата, основной UX) с Robot pattern
  • Интеграция с CI/CD (GitHub Actions, Firebase Test Lab)
  • Документация по запуску и поддержке тестов
  • Обучение команды (1–2 часа воркшопа)

Мы разработали UI-тесты для 15+ Android-приложений, средняя стабильность — 97%, максимальный проект — 1200 тестов. Среднее время прогона 100 тестов — 15 минут вместо 2 часов без оптимизации.

Срок: от 3 до 10 дней в зависимости от сложности приложения. Стоимость рассчитывается индивидуально. Если вам нужна помощь с внедрением — свяжитесь с нами, мы проведём аудит и предложим решение. Закажите разработку тестового suite — гарантируем стабильность >95% и месяц сопровождения.

Чек-лист для стабильных UI-тестов
  1. Всегда регистрируйте IdlingResource для всех фоновых потоков.
  2. Не используйте Thread.sleep() — используйте явное ожидание через IdlingResource.
  3. Убедитесь, что анимации отключены в тестовом профиле устройства.
  4. Запускайте тесты на реальных устройствах через Firebase Test Lab.
  5. Очищайте состояние между тестами (clearState в @Before).
  6. Используйте Robot pattern для читаемости и повторного использования.