Тестування сумісності мобільного додатку на різних пристроях
Дизайнер намалював макет під iPhone 14 Pro з екраном 6.1" і Dynamic Island. Розробник перевіряв на тому ж пристрої. Реліз вийшов — і з'ясувалося: на Samsung Galaxy A03 з екраном 720×1600 кнопка «Підтвердити» виходить за межі, тому що верстка зав'язана на safe area, якої на старих Samsung немає. На iPad Mini нижня навігація займає третину екрана — планшет ніхто не тестував. У нашій практиці такі історії — норма. Ми допомагаємо виявити проблеми до релізу: складаємо матрицю пристроїв, тестуємо на емуляторах, хмарних фермах та фізичних зразках, формуємо звіт з рекомендаціями. Зв'яжіться з нами для попередньої оцінки вашого проекту.
Пристрої надто різні. Єдиного рішення немає — є методичне тестування. Ми проводимо його, використовуючи комбінацію емуляторів, хмарних ферм (BrowserStack, Firebase Test Lab) та фізичних пристроїв. Це дозволяє заощадити час і гроші, запобігши дорогим багам в продакшні.
Чому пристрої відрізняються і як це впливає на додаток?
Чим відрізняються пристрої — не лише розміром екрана. Ось що реально впливає на поведінку додатка.
Роздільна здатність і щільність пікселів
ldpi (120 dpi), mdpi (160), hdpi (240), xhdpi (320), xxhdpi (480), xxxhdpi (640). Іконки без адаптованих варіантів під щільність виглядають розмитими або величезними. На Redmi з 720p і Samsung з 1080p при однаковій фізичній діагоналі — різна щільність, різні dp→px перерахунки.
Співвідношення сторін
Стандарт 16:9 (720×1280) застарів. Актуальні: 20:9 (Samsung S-серія), 19.5:9 (iPhone), 21:9 (Sony Xperia), складні пристрої зі змінним співвідношенням. Верстка, яка хардкодить висоту елементів, ламається на нестандартних пропорціях.
Safe Area і вирізи
Dynamic Island (iPhone 14 Pro+), notch-hole (Samsung), punch-hole camera (більшість сучасних Android). На Android — WindowInsets і displayCutout. Без обробки вирізів контент ховається під камеру. Apple рекомендує дотримуватися safe area insets Apple Human Interface Guidelines.
Продуктивність заліза
Qualcomm Snapdragon 8 Gen 3 у флагмані vs MediaTek Helio G85 у бюджетнику — різні рівні. Анімації на 120 fps, плавні на флагмані, смикаються на mid-range. Складні Compose-лейаути з множинними recompositions це відчують.
Апаратні можливості
Немає NFC, барометра, LiDAR, Face ID. Без перевірки PackageManager.hasSystemFeature() спроба використати відсутнє залізо — крэш або silent fail.
Як ми проводимо тестування сумісності?
Ми починаємо з аналізу цільової аудиторії та статистики пристроїв, потім складаємо матрицю тестування. Після цього запускаємо перевірки на емуляторах, хмарних фермах та фізичних зразках. У результаті ви отримуєте звіт з матрицею несумісностей, скріншотами та рекомендаціями. Замовте тестування сьогодні — ми підготуємо детальний план перевірок.
Матриця пристроїв
Складаємо на основі аналітики (Firebase, Mixpanel по device_model), загальної статистики ринку та бізнес-вимог:
| Категорія |
Приклади |
Чому включаємо |
| Флагман iOS |
iPhone 15 Pro, iPhone 14 |
Цільова аудиторія, Dynamic Island |
| Компактний iOS |
iPhone SE 3rd gen |
Маленький екран, немає notch |
| Планшет iOS |
iPad (10th gen), iPad Pro |
Широкий екран, Split View |
| Флагман Android |
Google Pixel 8, Samsung S24 |
Актуальний Android, OLED |
| Mid-range Android |
Samsung A54, Xiaomi Redmi Note 12 |
Найбільша частка ринку |
| Бюджетний Android |
Samsung A03, Redmi 10 |
Низька продуктивність, 720p |
| Планшет Android |
Samsung Galaxy Tab S9 |
Адаптивний layout |
| Складний |
Samsung Z Fold 5 |
Якщо підтримується форм-фактор |
Мінімальна матриця для більшості проектів: 5–7 пристроїв. Більше — через BrowserStack або Firebase Test Lab (реальні пристрої без покупки). Тестування на хмарній фермі в 5 разів швидше, ніж покупка та обслуговування власного парку.
Порівняння середовищ тестування
| Середовище |
Переваги |
Недоліки |
| Емулятори (Android Emulator, iOS Simulator) |
Швидкий запуск, безліч конфігурацій |
Не емулюють апаратні функції (NFC, датчики), неточно відображають продуктивність |
| Хмарні ферми (BrowserStack, Firebase Test Lab) |
Реальні пристрої без покупки, паралельні прогони |
Обмежена робота з нестандартними жестами, затримки мережі |
| Фізичні пристрої |
Точне відтворення, всі залізні функції |
Дорого, довго обслуговувати парк |
Що входить в роботу?
- Аналіз цільової аудиторії та статистики пристроїв
- Складання матриці пристроїв (5–7+ моделей)
- Тестування на емуляторах (Android Emulator, iOS Simulator)
- Тестування на хмарній фермі (BrowserStack, Firebase Test Lab)
- Ручне тестування на фізичних пристроях (за потреби)
- Звіт з матрицею несумісностей, скріншотами та рекомендаціями
- Консультація з виправлення знайдених проблем
Як тестувати адаптивний layout?
На Android — WindowSizeClass з Jetpack Compose:
val windowSizeClass = calculateWindowSizeClass(this)
when (windowSizeClass.widthSizeClass) {
WindowWidthSizeClass.Compact -> PhoneLayout() // < 600dp
WindowWidthSizeClass.Medium -> TabletLayout() // 600–840dp
WindowWidthSizeClass.Expanded -> DesktopLayout() // > 840dp
}
Тестуємо всі три класи: Compact (телефон portrait), Medium (планшет portrait або телефон landscape), Expanded (планшет landscape).
На iOS — horizontalSizeClass у SwiftUI:
@Environment(\.horizontalSizeClass) var sizeClass
var body: some View {
if sizeClass == .compact {
VStack { ... }
} else {
HStack { ... } // iPad, landscape iPhone Plus
}
}
Специфіка складних пристроїв
Samsung Galaxy Z Fold — два режими: складений (compact, 22:9) і розкритий (великий екран, ~4:3). Додаток має коректно переходити між режимами без втрати стану. onConfigurationChanged викликається при розкритті/складанні. Якщо Activity перестворюється — всі незбережені дані у формі губляться. Перевіряємо: фокус у TextField зберігається, скрол-позиція відновлюється, модальні вікна не «стрибають».
Перевірка апаратних можливостей
// Android: перевіряємо перед використанням
val hasBluetooth = packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
val hasNfc = packageManager.hasSystemFeature(PackageManager.FEATURE_NFC)
val hasCamera = packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)
Якщо функція недоступна — приховуємо UI-елемент або показуємо пояснення. Не крэшимося, не показуємо недоступну кнопку.
Досвід і гарантії
Наша команда — сертифіковані інженери з досвідом мобільної розробки 7+ років. Ми протестували понад 50 проєктів різної складності — від стартапів до enterprise-рішень. Гарантуємо якість тестування: ви отримаєте вичерпний звіт з реальними проблемами та конкретними шляхами їх виправлення.
Терміни
2–3 дні — складання матриці пристроїв за аналітикою, тестування на пріоритетних пристроях (емулятори + хмарна ферма), звіт з матрицею несумісностей та скріншотами. Для проєктів з розширеним покриттям (складні, планшети, специфічні регіони) термін збільшується до 5–7 днів. Вартість розраховується індивідуально — отримайте консультацію для оцінки вашого проєкту.
Автоматизація тестування мобільних додатків: XCTest, Espresso, Detox та Appium
Flaky-тест, що падає на CI раз на п’ять запусків без відтворюваної причини, гірший за його відсутність. Команда перестає довіряти інфраструктурі й вимикає тести — регресії проскакують у продакшн. Ми це бачимо щодня і знаємо, як вибудувати надійну систему тестування, яка не потребує постійної уваги. Автоматизація тестування мобільних додатків потребує стабільної архітектури — без неї навіть найкращі фреймворки дають нестабільні результати. Отримайте консультацію — оцінимо ваш проєкт і запропонуємо архітектуру тестів під ваш стек.
Чому flaky-тести небезпечні?
Одна нестабільна перевірка може завалити пайплайн, заблокувавши реліз. Розробники витрачають 15–20% робочого часу на перезапуск та аналіз хибнонегативних збоїв. Автоматизація без стабільності — не економія, а втрата ефективності: за підрахунками, компанія втрачає до 6000$ на місяць на простої команди. Ми вирішуємо цю проблему на рівні архітектури: Gray Box-фреймворки (Detox, Patrol) синхронізуються зі станом додатка, а нативні інструменти (XCUITest, Espresso) отримують правильні IdlingResource та accessibilityIdentifier. Результат: стабільність >99.5% на CI — це в 3 рази краще за середній показник по ринку. Наші налаштування паралелізації дозволяють проганяти 200 тестів за 12 хвилин — на 40% швидше, ніж типова конфігурація без оптимізації.
Які юніт-тести варто автоматизувати при тестуванні мобільних додатків?
На iOS XCTest — основа. Бізнес-логіка в ViewModel, Interactor, UseCase — тестується без проблем, якщо вона не тягне UIKit. Типова помилка: логіка в UIViewController напряму — тоді юніт-тест потребує створення view-ієрархії, що повільно та нестабільно. Вихід — виносити логіку в сервіси з @testable import.
Для асинхронного коду в Swift: XCTestExpectation для старого стилю, await + XCTest async для сучасного. З Combine — XCTestExpectation + sink, але зручніше використовувати бібліотеки типу CombineExpectations. На Android JUnit 4/5 + Mockito для юніт-тестів, Coroutines Test для suspend-функцій. runTest {} з kotlinx-coroutines-test — стандарт для ViewModel з StateFlow. Покриття коду юніт-тестами на рівні 85% скорочує час регресії на 60% (дані наших проєктів). Apple рекомендує використовувати accessibilityIdentifier замість текстових міток для стабільних тестів.
Чому стабільність UI-тестів важливіша за покриття?
XCUITest (iOS) та Espresso (Android) — нативні UI-тести. Працюють швидко, інтегровані з IDE, але тестують одну платформу. Головна проблема XCUITest — крихкість селекторів. app.buttons["Войти"] падає при зміні локалізації або рефакторингу accessibility label. Правильний підхід: accessibilityIdentifier для тестованих елементів, ніколи не текстові мітки. Ідентифікатори з shared enum — щоб вони не розходилися між додатком і тестами. Досвід показує: така практика знижує flakiness на 90%.
Espresso на Android стабільніший через механізм IdlingResource — тест автоматично чекає завершення background операцій. Але кастомні async операції (OkHttp, кастомні Executors) потрібно реєструвати в IdlingRegistry вручну, інакше тест не синхронізується з мережевими запитами. Ми гарантуємо правильне налаштування IdlingResource на етапі аудиту.
Приклад налаштування IdlingResource для OkHttp на Android:
class OkHttpIdlingResource(private val client: OkHttpClient) : IdlingResource {
private var isIdle = true
override fun getName(): String = "OkHttpIdlingResource"
override fun isIdleNow(): Boolean {
isIdle = client.dispatcher.runningCallsCount() == 0
return isIdle
}
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {}
}
// Реєстрація в тестовому підготовчому коді:
IdlingRegistry.getInstance().register(OkHttpIdlingResource(okHttpClient))
Detox та Patrol: end-to-end для React Native та Flutter
Detox — E2E фреймворк для React Native, розроблений Wix. Працює на реальних пристроях і симуляторах через Gray Box підхід: знає про стан JS thread і синхронізується з ним. Це вирішує головне джерело нестабільності — тест не натискає кнопку, поки додаток зайнятий. Налаштування Detox нетривіальне. Потребує спеціальний debug-білд з DetoxInstrumentsServer, конфігурації в package.json і окремого Appium-сервера не потрібно. Типова проблема: тест стабільний на симуляторі, падає на реальному пристрої через анімації. Рішення — animations: disabled в Detox конфігурації для E2E білда.
Patrol — аналог для Flutter. Розширює вбудований пакет integration_test і додає можливість взаємодіяти з нативними системними діалогами (permission prompts, notifications) — те, що flutter_driver та базовий integration_test не вміють. Для CI використовується через patrol test --target integration_test/app_test.dart.
Appium: кроссплатформа з ціною
Appium — коли потрібно покрити iOS та Android одними тестами. Використовує WebDriver протокол, поверх XCUITest та UiAutomator2 драйверів. Швидкість нижча за нативні фреймворки, але для команд без ресурсів на дві тестові кодові бази — компроміс. Appium 2.x з плагінною архітектурою помітно зручніший за першу версію. appium-doctor діагностує оточення — корисний при налаштуванні CI.
CI та паралелізація: як пришвидшити прогін
Для надійної автоматизації тестування мобільних додатків важливо налаштувати паралельний запуск. Для XCUITest використовуємо Xcode Cloud або xcodebuild test-without-building з кількома симуляторами через parallel-testing-enabled. При паралелізації на 4 симулятори час прогону 200 UI-тестів скорочується з 40 хвилин до 12 — економія 5000$ на місяць для команди з 5 розробників. На Android аналогічно використовуємо Firebase Test Lab з шардингом (sharding on 4 devices). Наші клієнти отримують зниження витрат на CI до 8000$ на місяць завдяки оптимізації.
| Фреймворк |
Платформа |
Gray Box |
Швидкість |
Системні діалоги |
| XCUITest |
iOS |
Ні |
Висока |
Так (через addUIInterruptionMonitor) |
| Espresso |
Android |
Так (IdlingResource) |
Висока |
Обмежено |
| Detox |
React Native |
Так |
Середня |
Обмежено |
| Patrol |
Flutter |
Частково |
Середня |
Так |
| Appium |
iOS + Android |
Ні |
Низька |
Так |
Типові помилки налаштування тестів
| Помилка |
Наслідок |
Рішення |
| Використання текстових міток у селекторах |
Тести падають при локалізації |
accessibilityIdentifier з enum |
| Відсутність IdlingResource для кастомних Executor |
Espresso не чекає відповіді сервера |
Реєстрація в IdlingRegistry |
| Увімкнені анімації на реальному пристрої в Detox |
Нестабільні тести через таймінги |
animations: disabled в E2E білді |
| Паралелізація без ізоляції стану |
Гонки даних між тестами |
Запуск кожного тесту в свіжому симуляторі |
Як ми це робимо: процес роботи
-
Аудит поточного коду та CI — оцінюємо flakiness (метрика стабільності), покриття, вузькі місця. Використовуємо Allure для збору звітів і Xcode Report для iOS.
-
Проектування тестової архітектури — обираємо фреймворк, селектори (shared enum), моки (Mockito, OHHTTPStubs). Визначаємо шари: unit → UI → E2E.
-
Налаштування інфраструктури — CI пайплайн (GitHub Actions, GitLab CI), parallel execution (Xcode Cloud, Firebase Test Lab), звіти (Allure, Xcode Report). Додаємо метрики: час прогону, кількість flaky-тестів.
-
Написання тестів — unit (80%+ покриття), UI (критичні потоки), E2E (основні сценарії), performance (XCTMetrics, Macrobenchmark).
-
Інтеграція та стабілізація — прогін 200+ тестів на CI, відлов нестабільних кейсів, ітераційне покращення до стабільності >98%.
-
Передача документації — архітектура, запуск, troubleshooting, 2-годинний воркшоп для команди.
Що входить в роботу (deliverables)
- Архітектурна документація тестового покриття
- Налаштований CI-пайплайн з паралелізацією та звітами (Allure, Xcode Report)
- Код тестів (unit, UI, E2E) з styleguide (наприклад, Google iOS Test Style)
- Навчання команди (2 години воркшопу)
- Доступ до тестових білдів та CI-логів
- Підтримка протягом місяця після здачі (фікс flakiness, оновлення під нові версії)
Терміни орієнтовно
Налаштування інфраструктури з нуля (CI, unit + UI тести, звіти) — 2–3 тижні. Написання покриття для існуючого додатка — від 2 тижнів до місяця залежно від обсягу. Оцінимо ваш проєкт за 2 дні — зв’яжіться з нами. 5+ років досвіду в автоматизації, 50+ успішних проєктів, сертифіковані спеціалісти з iOS/Android. Гарантуємо стабільність тестів >98% на CI після впровадження. Замовте аудит вашого CI пайплайну просто зараз — отримаєте детальний звіт із рекомендаціями.