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 для читабельності та повторного використання.