Тестването на мобилни приложения е процес на проверка, че приложението работи коректно, не се срива и отговаря на изискванията. Според Software Testing Help (2025), автоматизираното тестване намалява времето за регресионни проверки със 70–80% в сравнение с ръчното тестване. В тази статия ще разгледаме нивата на тестване, инструментите за iOS и Android, TDD и BDD, както и CI/CD за тестове.
Основни моменти
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 тестовете, интеграционните тестове използват реални или близки до реалността зависимости (например база данни в паметта или мок сървър). 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 тестване. Работи чрез идентификатори за достъпност: XCUIElementQuery намира бутони, полета за въвеждане, таблици по етикет, идентификатор или тип. 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 е лесен за писане и стабилен благодарение на вграденото изчакване за idle състояние. UI Automator е рамка за тестове между приложения, която може да взаимодейства със системни елементи (диалози за разрешения, сянка за известия).
Detox е сиво-сив E2E рамка за тестване на React Native мобилни приложения от Wix. Detox работи на двете платформи от една тестова кодова база, използвайки Espresso (Android) и XCUITest (iOS) под капака. Detox автоматично чака приложението да стане idle (без анимации, мрежови заявки, таймери) и едва тогава изпълнява следващото действие.
Appium е универсална крос платформена рамка, поддържаща Android, iOS, Web и хибридни приложения. Appium използва WebDriver протокол и поддържа всякакви езици за програмиране (Java, Python, JS, Ruby). Appium Server работи като HTTP сървър, който превежда команди в native UI Automator / XCUITest команди. Основният недостатък на Appium е скоростта: тестовете се изпълняват по-бавно от native 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 срещу Stub срещу 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 г. Ще ви консултираме и ще предложим най-доброто решение.