Основы тестирования iOS

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

Жизненный цикл iOS-приложений

Понимание жизненного цикла критично для мобильных тестировщиков, потому что многие баги возникают при переходах между состояниями.

Состояния приложения

Не запущено → Неактивно → Активно → Фоновое → Приостановлено → Завершено
СостояниеОписаниеФокус тестирования
Не запущеноПриложение не запускалось или было завершеноПроизводительность холодного старта
НеактивноНа переднем плане, но не получает событияОбработка прерываний
АктивноНа переднем плане, получает событияОбычная функциональность
ФоновоеВыполняет код, но не видимоЗавершение фоновых задач
ПриостановленоВ памяти, но код не выполняетсяВосстановление состояния
ЗавершеноУдалено из памятиСохранение данных

Критические сценарии тестирования

  1. Холодный vs тёплый старт: Замерьте запуск из завершённого состояния (холодный) против приостановленного (тёплый). Пользователи замечают, если холодный старт занимает более 2 секунд.

  2. Прерывания: Проверьте, что происходит при:

    • Входящем звонке во время критической операции
    • Активации Siri
    • Появлении предупреждения о низком заряде
    • Срабатывании таймера или будильника
    • Открытии Центра управления
  3. Из фона на передний план: После 30+ минут в фоне приложение корректно восстанавливается? Проверьте:

    • Истёкшие токены авторизации
    • Устаревшие данные на экране
    • Потерянный ввод форм
    • Разорванные WebSocket-соединения
  4. Давление на память: iOS может завершить приостановленные приложения в любой момент. Тестируйте восстановление состояния после принудительного завершения.

Инструменты тестирования Xcode

XCUITest

XCUITest — нативный фреймворк UI-тестирования Apple, взаимодействующий с приложением через систему доступности.

// Пример XCUITest
func testLoginFlow() {
    let app = XCUIApplication()
    app.launch()

    let emailField = app.textFields["Email"]
    emailField.tap()
    emailField.typeText("user@example.com")

    let passwordField = app.secureTextFields["Password"]
    passwordField.tap()
    passwordField.typeText("password123")

    app.buttons["Sign In"].tap()

    XCTAssertTrue(app.staticTexts["Welcome"].waitForExistence(timeout: 5))
}

Xcode Instruments

Instruments — инструментарий профилирования, входящий в Xcode:

ИнструментНазначениеКогда использовать
Time ProfilerАнализ использования CPUПриложение ощущается медленным
AllocationsОтслеживание использования памятиВысокое потребление памяти
LeaksОбнаружение утечек памятиПамять растёт со временем
Energy LogПотребление батареиРасход батареи в фоне
NetworkПрофилирование сетевых запросовМедленная загрузка данных

Система разрешений iOS

iOS имеет строгую модель разрешений. Приложения должны запрашивать разрешение на доступ к чувствительным ресурсам.

Разрешения для тестирования

РазрешениеПервый запросПосле отказаСпособ сброса
КамераСистемный диалогЧерез НастройкиНастройки > Конфиденциальность > Камера
Геолокация3 варианта: Однократно, При использовании, ВсегдаТолько НастройкиНастройки > Конфиденциальность > Геолокация
УведомленияСистемный диалогТолько НастройкиНастройки > Уведомления
ФотоДиалог с ограниченным/полным доступомТолько НастройкиНастройки > Конфиденциальность > Фото

Чек-лист тестирования разрешений

  • Первый запрос разрешения показывает корректный диалог
  • Приложение грамотно обрабатывает отказ (без краша, полезное сообщение)
  • Приложение работает с ограниченным доступом к фото (iOS 14+)
  • Разрешение геолокации «При использовании» vs «Всегда» работает корректно
  • Отзыв разрешения в Настройках не вызывает краш
  • App Tracking Transparency (iOS 14.5+) появляется до любого отслеживания

Подготовка к ревью App Store

Apple проверяет каждую отправку приложения. Типичные причины отклонения:

Топ-5 причин отклонения

  1. Баги и краши (самая частая) — тестируйте все флоу на минимальной поддерживаемой версии iOS
  2. Битые ссылки и placeholder-контент — проверьте все URL в приложении
  3. Неполные метаданные — скриншоты должны соответствовать текущему UI
  4. Проблемы производительности — запуск должен завершаться за разумное время
  5. Нарушения гайдлайнов дизайна — используйте стандартные паттерны навигации iOS

Чек-лист перед отправкой

□ Протестировано на минимальной поддерживаемой версии iOS
□ Протестировано на последней версии iOS
□ Все диалоги разрешений проверены (выдача и отказ)
□ Dark Mode проверен на всех экранах
□ Dynamic Type проверен (максимальный и минимальный размеры)
□ Базовая навигация VoiceOver работает
□ Нет крашей в логах Xcode Organizer
□ Все ссылки рабочие
□ Privacy manifest обновлён (iOS 17+)
□ Скриншоты соответствуют текущему UI

Упражнение: Охота за багами iOS

Сценарий: Вы тестируете приложение заказа еды на iOS, готовящееся к первой отправке в App Store.

Определите потенциальные баги:

  1. Пользователь добавляет товары в корзину, получает звонок, возвращается через 5 минут
  2. Пользователь даёт разрешение на геолокацию «При использовании», но приложению нужна геолокация для отслеживания доставки в фоне
  3. У пользователя Dynamic Type установлен на максимальный размер доступности
Решение
  1. Восстановление состояния: Данные корзины могут быть потеряны, если приложение было приостановлено и завершено. Проверить: товары в корзине, актуальность цен, корректное возобновление таймеров.

  2. Несоответствие разрешения геолокации: С разрешением «При использовании» приложение теряет доступ к геолокации в фоне. Отслеживание доставки не будет работать. Нужно запрашивать «Всегда» или объяснять необходимость.

  3. Переполнение Dynamic Type: Большие размеры шрифта часто вызывают: обрезку текста, наложение меток, слишком маленькие кнопки, нежелательный горизонтальный скроллинг.

Советы из продакшен-опыта

Совет 1: Тестируйте на самой старой поддерживаемой версии iOS первой. Большинство крашей происходит на старых версиях, где устаревшие API могут вести себя иначе.

Совет 2: Используйте Xcode Organizer для реальных данных о крашах. После бета-тестирования через TestFlight Organizer показывает реальные отчёты о крашах от тестировщиков.

Совет 3: Тестируйте состояние «Не определено» для разрешений. iOS показывает диалог разрешения только один раз. Проверьте поведение приложения, когда разрешение никогда не запрашивалось vs когда было явно отклонено.

Ключевые выводы

  • Переходы жизненного цикла iOS — частый источник багов, тестируйте прерывания и восстановление
  • XCUITest — нативный фреймворк UI-автоматизации iOS
  • Xcode Instruments необходим для профилирования производительности и памяти
  • Тестирование разрешений должно покрывать первый запрос, отказ, отзыв и ограниченный доступ
  • Отклонения App Store обычно вызваны багами, незавершёнными функциями или нарушением гайдлайнов