Особенность 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 МБ, длинную запись экрана стоит резать.
С чего начать
- Добавьте
xcbeautify --report junitв шаг тестов и выгрузку сwhen: always. - Проставьте ключи кейсов в именах UI-тестов для критичных сценариев.
- Заведите конфигурации устройств и стартуйте план по ним перед релизом.
- Чек-лист публикации в 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 — один драйвер, два прогона, честный отчёт