Каковы ключевые различия в тестировании приложений для iOS и Android?

Ответ

Различия обусловлены экосистемами платформ: фрагментацией, инструментами, языками и процессами публикации.

1. Фрагментация устройств и ОС

  • Android: Высокая фрагментация. Множество производителей, моделей, размеров экранов, версий ОС и кастомных прошивок. Требуется тестирование на широком наборе устройств.
  • iOS: Низкая фрагментация. Ограниченный набор устройств Apple и несколько актуальных версий iOS. Проще покрыть основные конфигурации.

2. Инструменты и среды разработки

  • iOS: Основная среда — Xcode. Для UI-тестирования используется XCTest (фреймворк Apple). Для дистрибуции бета-версий — TestFlight.
  • Android: Основная среда — Android Studio. Для UI-тестирования используются Espresso (для View-системы) и Jetpack Compose Testing (для Compose). Для бета-тестирования и тестов на реальных устройствах — Firebase Test Lab.

3. Языки и фреймворки для автоматизации

  • iOS: Нативные тесты пишутся на Swift (реже Objective-C) с XCTest. Для кроссплатформенной автоматизации можно использовать Appium (с WebDriverAgent).
  • Android: Нативные тесты пишутся на Kotlin (реже Java) с Espresso/Jetpack. Appium использует UiAutomator2.

4. Примеры UI-тестов

iOS (Swift, XCTest UI Tests):

func testLoginSuccess() {
    let app = XCUIApplication()
    app.launch()
    // Ввод данных, знание accessibility идентификаторов
    app.textFields["usernameField"].tap()
    app.textFields["usernameField"].typeText("user@test.com")
    app.secureTextFields["passwordField"].tap()
    app.secureTextFields["passwordField"].typeText("password")
    app.buttons["loginButton"].tap()
    // Проверка результата по появлению элемента
    XCTAssertTrue(app.staticTexts["welcomeMessage"].waitForExistence(timeout: 5))
}

Android (Kotlin, Espresso):

@Test
fun testLoginSuccess() {
    // Ввод данных и действия с View, найденными по ID из R.java
    onView(withId(R.id.usernameField))
        .perform(typeText("user@test.com"), closeSoftKeyboard())
    onView(withId(R.id.passwordField))
        .perform(typeText("password"), closeSoftKeyboard())
    onView(withId(R.id.loginButton)).perform(click())
    // Проверка результата
    onView(withId(R.id.welcomeMessage))
        .check(matches(isDisplayed()))
}

5. Процесс публикации и ревью

  • iOS (App Store): Строгий и часто непредсказуемый процесс ревью от Apple. Могут отклонять из-за нарушений гайдлайнов, использования приватных API. Время ревью — от нескольких часов до дней.
  • Android (Google Play): Более формализованный и предсказуемый процесс автоматизированной проверки. Ручное ревью проводится выборочно или для определенных категорий приложений. Публикация обычно происходит быстрее.

6. Другие аспекты

  • Навигация: Разные жесты и паттерны (кнопка "Назад" в Android vs. swipe-жесты в iOS).
  • Разрешения: Модели запроса и управления разрешениями отличаются.
  • Тестирование сборки: В Android нужно тестировать разные варианты сборки (debug, release, с разными типами подписи).

Ответ 18+ 🔞

Да ты посмотри, какая, блядь, разница! Как будто на разных планетах живут эти iOS и Android. Один как марсианин, другой как венерианец, и оба друг друга в гробу видали.

Ну, короче, смотри, почему так выходит.

1. Фрагментация, или "Где мой девайс, сука?"

  • Android: Это же пиздец, а не фрагментация! Тут один производитель выпустил три телефона, другой — пять, у третьего вообще холодильник с экраном. Версий ОС — дохуя, и все живые. Кастомные прошивки? Да сколько угодно! Тестировщику одно слово: страдай. Нужно ловить баги на сотне разных железяк, иначе пользователь пришлёт тебя нахуй с криком "У меня не работает!".
  • iOS: А тут, блядь, рай земной. Яблочко, оно такое, одно. Девайсов — раз-два и обчёлся. Версий системы — пара актуальных. Сесть, выпить кофе, протестировать на трёх-пяти устройствах — и вроде как всё, можно жить. Проще некуда.

2. Инструменты, или "В какой песочнице копаем?"

  • iOS: Сидишь в Xcode, как в монастыре. Для UI-тестов у тебя родной XCTest. Хочешь бета-тест устроить? TestFlight тебе в руки. Всё от одного папы — Купертино.
  • Android: Добро пожаловать в Android Studio. Для тестов у тебя Espresso (если на старых вьюхах сидишь) или Jetpack Compose Testing (если трендовый и модный). А чтобы на реальных девайсах всё проверить — есть Firebase Test Lab, чтоб его.

3. Языки, или "На каком наречии изъясняемся?"

  • iOS: Родной — Swift (ну или древний Objective-C, если мазохист). Пишешь в XCTest — и всё, красота. Ну или можешь Appium притащить, но это уже как пригласить француза на русскую пьянку — вроде работает, но неестественно.
  • Android: Тут царь — Kotlin. На нём и пишешь Espresso-тесты. Java? Ну, если старовер. Appium тут тоже пролезет, но через UiAutomator2.

4. Примеры кода, или "Смотри, как я умею!"

Вот, смотри, один и тот же тест — логин проверить. А пишется, будто для разных видов приматов.

iOS (Swift, XCTest UI Tests):

func testLoginSuccess() {
    let app = XCUIApplication()
    app.launch()
    // Тыкаем в поля по accessibility id — без них нихуя не найдёшь
    app.textFields["usernameField"].tap()
    app.textFields["usernameField"].typeText("user@test.com")
    app.secureTextFields["passwordField"].tap()
    app.secureTextFields["passwordField"].typeText("password")
    app.buttons["loginButton"].tap()
    // Ждём, появится ли приветствие, или всё пошло по пизде
    XCTAssertTrue(app.staticTexts["welcomeMessage"].waitForExistence(timeout: 5))
}

Android (Kotlin, Espresso):

@Test
fun testLoginSuccess() {
    // Ищем вьюхи по их ID — всё чинно, благородно
    onView(withId(R.id.usernameField))
        .perform(typeText("user@test.com"), closeSoftKeyboard())
    onView(withId(R.id.passwordField))
        .perform(typeText("password"), closeSoftKeyboard())
    onView(withId(R.id.loginButton)).perform(click())
    // Проверяем, видно ли нам приветствие, или мы облажались
    onView(withId(R.id.welcomeMessage))
        .check(matches(isDisplayed()))
}

Видишь? Одна логика, а синтаксис — будто с разных планет упал.

5. Публикация, или "Кто тут барин?"

  • iOS (App Store): А вот это, ёпта, настоящая лотерея! Отправляешь сборку на ревью к яблочникам и молишься. Они могут зарубить из-за какой-нибудь хуйни: "А у вас кнопка на 2 пикселя не по гайдлайну", или "А это у вас приватное API пахнет". Ждёшь от нескольких часов до недели, как повезёт. Нервы нахуй.
  • Android (Google Play): Тут попроще. Автоматические проверки пробежались — и вроде норм. Ручное ревью — штука редкая, чаще для всяких казино и политики. Выкатился апк быстрее, дышишь свободнее.

6. Мелочи, которые бесят

  • Навигация: На Android кнопка "Назад" есть всегда. На iOS её может и не быть, там свайпай, как обезьяна.
  • Разрешения: Запрашивать и управлять ими нужно по-разному, иди учи две документации.
  • Сборки (Android): А вот это весёлое. Тебе же надо проверить не только debug, но и release, да ещё с разными типами подписи. А то выкатишь в прод, а там — пиzдец, потому что в debug-сборке всё работало, а в release сломалась какая-нибудь оптимизация.

Вот и вся, блядь, разница. Два мира, два Шапиро. А тестировщик между ними — как тот Герасим, только вместо Муму у него два десятка девайсов и ведро кофе.