Мобильные приложения

iOS — результаты XCTest в покрытие, ручной регресс по версиям

Xcode складывает результаты в бандл xcresult, а QA Деск принимает JUnit XML — между ними один шаг конвертации в пайплайне; после него автотесты и ручные проверки на устройствах живут в одном покрытии.

Особенность iOS: формат отчёта

Android отдаёт JUnit XML из коробки. Xcode — нет: xcodebuild test пишет бандл .xcresult, бинарный и понятный только инструментам Apple. Это главная техническая разница между двумя платформами с точки зрения тест-менеджмента, и её надо закрыть в пайплайне один раз.

Рабочих способов два. Первый — xcbeautify или xcpretty с репортёром JUnit прямо в момент сборки:

xcodebuild test -scheme App -destination 'platform=iOS Simulator,name=iPhone 15' \
  -resultBundlePath build/App.xcresult | xcbeautify --report junit --report-path build/junit

Второй — xcrun xcresulttool get --format json с последующей конвертацией в JUnit; так делают, когда нужны данные из бандла, которых в потоке сборки нет. Приём .xcresult напрямую — в дорожной карте, пока конвертация остаётся на стороне CI.

Загрузка в прогон

./qadesk-cli upload --run "App ui-tests" --env stage --platform ios \
  --build "$(agvtool what-version -terse)" build/junit

--platform ios и номер сборки из CFBundleVersion ложатся в поля прогона. Повтор задания не создаёт второй прогон — приём идемпотентен по паре «прогон CI + попытка».

Ключ кейса

Ключ вида QAD-C42 держится в имени тестового метода — XCTest переносит его в classname и имя теста, приём находит его в любом из двух мест:

func test_QAD_C42_loginWithValidPassword() throws {
    let app = XCUIApplication()
    app.launch()
    // …
}

Регистр и подчёркивания не мешают распознаванию. Тесты без ключа возвращаются поимённо с причиной и в прогон не попадают.

Шарды и повторы

UI-тесты на iOS долгие, и их часто параллелят по симуляторам (-parallel-testing-enabled) или по классам. Приём идемпотентен по паре «прогон CI + попытка»: разные шарды одного пайплайна — это разное содержимое под одним ключом, поэтому у каждого свой --attempt или --ci-run-id; одинаковый ключ с другим отчётом получит отказ, а не тихую перезапись. Если один кейс встретился дважды — ретрай прошёл со второго раза, — в прогон попадает худший исход.

Ручной регресс по устройствам и версиям

Apple держит парк проще, чем Android, но обязательные конфигурации всё равно есть: последняя iOS на актуальном iPhone, минимальная поддерживаемая версия, iPad, если приложение универсальное, и как минимум одно физическое устройство — симулятор не проверяет ни пуши с продакшн-сертификатом, ни Face ID, ни реальную сеть.

В QA Деск конфигурация прогона — именованный набор значений: {device: iPhone 15, os: iOS 17.5}. План стартует сразу по нескольким конфигурациям, время исполнения считается по каждой строке.

Дефект и сборка

Дефект из упавшей строки наследует среду, платформу, сборку и конфигурацию; ссылка на прогон прикладывается автоматически. Номер сборки — то, что первым спрашивает разработчик, и то, что тестировщик чаще всего забывает написать: здесь он приходит из CI, а не из памяти. Запись экрана из xcrun simctl io booted recordVideo прикладывается вложением. Краш из Sentry заводится дефектом без рук — подробнее. Разработчику задача ставится в Битрикс24 или SourceCraft.

Чего в продукте нет

  • нет приёма .xcresult как формата — конвертация в JUnit остаётся в пайплайне;
  • нет запуска тестов и фермы устройств;
  • нет хранения больших видео: вложение до 8 МБ, длинную запись экрана стоит резать.

С чего начать

  1. Добавьте xcbeautify --report junit в шаг тестов и выгрузку с when: always.
  2. Проставьте ключи кейсов в именах UI-тестов для критичных сценариев.
  3. Заведите конфигурации устройств и стартуйте план по ним перед релизом.
  4. Чек-лист публикации в App Store и регресса после обновления iOS — в каталоге кейсов.

Попробуйте на своём проекте

Заведите проект, загрузите первый отчёт или заведите первый дефект — бесплатный тариф без карты. Нужно демо на ваших сценариях — напишите на hello@qadesk.ru.

Создать проект

Рядом по теме

Мобильные приложения

Android

Gradle пишет JUnit XML для каждого инструментального теста — QA Деск принимает его как есть и кладёт в покрытие рядом с ручными кейсами; конфигурации прогона превращают план в матрицу «устройство × версия ОС».

Android — отчёт с эмулятора и устройства, прогон по матрице
Мобильные приложения

Flutter

У кроссплатформенного приложения один набор кейсов и две платформы исполнения — конфигурации прогона в QA Деск позволяют не заводить кейсы дважды, а отчёты flutter test приезжают тем же CLI после конвертации в JUnit.

Flutter — один код, два прогона и одно покрытие
Мобильные приложения

Appium

Appium — самый частый выбор для мобильных автотестов вне кода приложения; отчёт даёт тот раннер, из которого вы его запускаете, а QA Деск принимает JUnit или Allure и кладёт результат в прогон нужной платформы.

Appium — один драйвер, два прогона, честный отчёт