Тестирование мобильных приложений — это процесс проверки того, что приложение работает корректно, не падает и соответствует требованиям. По данным Software Testing Help (2025), автоматизированное тестирование сокращает время регрессионных проверок на 70–80% по сравнению с ручным тестированием. В этой статье разберём уровни тестирования, инструменты для iOS и Android, TDD и BDD, а также CI/CD для тестов.
Главное
Unit-тесты — основа тестирования мобильных приложений. Они проверяют smallest unit кода — одну функцию, метод или класс в изоляции от остальной системы. В мобильной разработке unit-тесты пишутся на JUnit (Android) и XCTest (iOS). Хороший unit-тест должен быть быстрым, независимым и повторяемым — он не должен зависеть от сети, базы данных или UI-компонентов. Для изоляции используются test doubles: моки, стабы и фейки.
Mockito (Java/Kotlin) и MockK (Kotlin-first) — популярные библиотеки для создания мок-объектов на Android. На iOS для мокинга используются OCMock, Cuckoo или ручные протоколы. Правило: unit-тесты должны покрывать бизнес-логику и модели данных. UI-тесты не должны дублировать unit-тесты — они проверяют взаимодействие пользователя с интерфейсом.
Интеграционные тесты проверяют взаимодействие между компонентами: репозиторий с базой данных, ViewModel с API-сервисом, навигация между экранами. В отличие от unit-тестов, интеграционные используют реальные или приближенные к реальности зависимости (например, in-memory база данных или mock-сервер). Robolectric — фреймворк для запуска Android-тестов на JVM без эмулятора, что ускоряет интеграционные тесты в 10 раз.
Snapshot-тесты (Golden Tests) — особый вид интеграционных тестов, которые сравнивают отрисованный UI-компонент с эталонным изображением (snapshot). Если внешний вид изменился, тест падает — разработчик видит, что изменилось. Facebook SnapshotTestCase (iOS) и Shot (Android) — популярные инструменты для snapshot-тестирования.
E2E-тесты (end-to-end) проверяют полный пользовательский сценарий от начала до конца: запуск приложения, логин, совершение действия, проверка результата. UI-тесты — подмножество E2E, сфокусированное на интерфейсе. Инструменты: Espresso (Android), XCUITest (iOS), Detox (React Native). E2E-тесты самые медленные, поэтому их запускают отдельно на CI — обычно на ночных сборках.
XCTest — встроенный фреймворк Apple для unit-тестирования мобильных приложений. XCTestRunner запускает тесты на симуляторе или реальном устройстве. Тесты наследуются от XCTestCase, содержат setUp и tearDown для подготовки и очистки. XCTest включает XCTAssert для проверок (XCTAssertEqual, XCTAssertNil, XCTAssertTrue) и XCTWaiter для ожидания асинхронных операций.
Пример простого XCTest-теста: создание модели User, проверка корректности инициализации, форматирования имени и подсчёта возраста. Code Coverage в Xcode показывает, какие строки кода покрыты тестами — цель для коммерческих проектов: минимум 70–80% покрытия бизнес-логики. XCTest интегрирован с Xcode Server и CI-системами через xcodebuild test.
XCUITest — фреймворк Apple для UI-тестирования. Работает через accessibility-идентификаторы: XCUIElementQuery находит кнопки, поля ввода, таблицы по label, identifier или типу. XCUITest записывает последовательность действий (record/playback) и генерирует код теста. Важно: все UI-элементы должны иметь accessibilityIdentifier для стабильной работы тестов.
JUnit — базовый фреймворк для модульного тестирования мобильных приложений на Java/Kotlin. На Android используется JUnit 4 (последняя стабильная версия 4.13.2) и JUnit 5 для новых проектов. Mockito — библиотека для создания мок-объектов: when(mock.method()).thenReturn(value) — стандартный паттерн для изоляции тестируемого класса от зависимостей.
Пример JUnit-теста для Android:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class LoginViewModelTest {
@Mock
AuthRepository authRepository;
@Test
public void login_emptyEmail_returnsError() {
LoginViewModel vm = new LoginViewModel(authRepository);
String result = vm.login("", "password123");
assertEquals("Email cannot be empty", result);
verify(authRepository, never()).authenticate(any());
}
}
Espresso — фреймворк Google для UI-тестов Android. Espresso автоматически синхронизируется с UI-потоком: onView(withId(R.id.button)).perform(click()).check(matches(isDisplayed())). Espresso прост в написании и стабилен благодаря встроенному ожиданию идл-состояния приложения. UI Automator — фреймворк для кроссприложных тестов, который может взаимодействовать с системными элементами (диалогами разрешений, шторкой уведомлений).
Detox — серо-серый E2E-фреймворк для тестирования React Native мобильных приложений от Wix. Detox работает на обеих платформах из одной кодовой базы тестов, используя Espresso (Android) и XCUITest (iOS) под капотом. Detox автоматически ждёт, пока приложение станет идл (нет анимаций, сетевых запросов, таймеров), и только затем выполняет следующее действие.
Appium — универсальный кроссплатформенный фреймворк, поддерживающий Android, iOS, Web и гибридные приложения. Appium использует WebDriver протокол и подходит для любых языков программирования (Java, Python, JS, Ruby). Appium Server работает как HTTP-сервер, который транслирует команды в нативные UI Automator / XCUITest команды. Основной недостаток Appium — скорость: тесты выполняются медленнее, чем нативные Espresso или XCUITest.
| Критерий | iOS | Android |
|---|---|---|
| Unit-тесты | XCTest | JUnit 4/5 + Mockito |
| UI-тесты | XCUITest | Espresso, UI Automator |
| Snapshot-тесты | FBSnapshotTestCase | Shot, Roborazzi |
| Автоматизация жестов | XCUIGesture | UiAutomator touch |
| Code Coverage | Xcode Code Coverage | Jacoco |
| CI интеграция | xcodebuild test | Gradle connectedCheck |
TDD — методология тестирования мобильных приложений, при которой тест пишется до реализации кода. Цикл Red-Green-Refactor: (1) написать тест, который не проходит (Red), (2) написать минимальный код, чтобы тест прошёл (Green), (3) отрефакторить код, сохраняя прохождение теста. TDD даёт 100% покрытие тестами новой функциональности и чистую архитектуру, так как тест — это первая спецификация требования.
BDD — расширение TDD, где тесты пишутся на естественном языке в формате Given-When-Then. Given (контекст) — When (действие) — Then (ожидаемый результат). BDD-тесты понятны всем участникам команды: разработчикам, тестировщикам, аналитикам и заказчикам. Mock vs Stub vs Fake: Mock проверяет взаимодействие (был ли вызван метод), Stub возвращает фиксированные данные, Fake — упрощённая рабочая реализация (например, in-memory БД). В IT Sectr мы используем TDD для критичной бизнес-логики и BDD для приёмочных сценариев.
Test Doubles — общее название для объектов, заменяющих реальные зависимости в тестах. Их четыре типа: Dummy (объект для заполнения параметров, не используется), Stub (возвращает заданные значения), Spy (записывает вызовы для проверки), Mock (предопределяет ожидаемые вызовы). Понимание разницы критически важно для правильного проектирования тестов.
CI/CD — Continuous Integration и Continuous Delivery: практика автоматической сборки и тестирования мобильных приложений при каждом изменении кода. В мобильной разработке CI/CD пайплайн включает: линтинг, unit-тесты, интеграционные тесты, сборку APK/IPA и UI-тесты. GitHub Actions и Bitrise — популярные платформы для мобильного CI/CD. Тесты должны выполняться быстро: unit-тесты за 1–2 минуты, интеграционные за 5–10, UI-тесты за 15–30 минут.
Device Farm — ферма реальных устройств для тестирования. Firebase Test Lab (Android) и Xcode Cloud (iOS) предоставляют облачный доступ к сотням моделей устройств. Device Farm выявляет проблемы, которые не видны на эмуляторах: особенности экранов разных размеров, производительность на старых устройствах, проблемы с совместимостью. В IT Sectr мы используем Firebase Test Lab для Android и Xcode Cloud для iOS на регулярной основе.
Часто задаваемые вопросы
Для коммерческих проектов минимум 70–80% покрытия бизнес-логики. UI-код покрывать сложнее — для него достаточно 50%. Главное не процент, а качество тестов: тестируйте критичные сценарии, граничные случаи и обработку ошибок.
Mock проверяет взаимодействие — был ли вызван определённый метод с определёнными параметрами. Stub возвращает заранее заданные данные. Mock проверяет поведение, Stub — состояние.
Да, но только для критических сценариев: логин, регистрация, оформление заказа, платёж. UI-тесты медленные и хрупкие — не пишите тест на каждый экран. Сфокусируйтесь на E2E-сценариях пользователя.
Snapshot Test (Golden Test) сравнивает отрисованный UI-компонент с эталонным изображением. Если внешний вид изменился (шрифт, отступ, цвет), тест падает — разработчик проверяет, осознанное ли это изменение. Идеально для компонентных библиотек.
Запускайте E2E-тесты параллельно на нескольких устройствах, используйте Cloud Device Farm и разделяйте тесты на независимые группы. Оптимизируйте тесты: минимизируйте ожидания, используйте моки для сетевых запросов.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.