После выбора изображения из медиатеки приложению может потребоваться прочитать данные об ориентации, создать миниатюру, сжать исходный файл и отправить его. При работе с видео дополнительно появляются ветви, связанные с продолжительностью, кодеком и размером файла. Однократная ручная проверка на компьютере разработчика не доказывает, что следующая сборка сможет обработать тот же набор входных данных. Более надёжный подход — хранить медиафайлы в репозитории как тестовые фикстуры, сбрасывать отдельный симулятор на удалённом Mac и добавлять материалы в его медиатеку с помощью simctl addmedia.
Сначала определите границы проверки
Такие тесты должны проверять интерфейс между приложением и системной медиатекой, а не автоматизировать приложение «Фото». Рекомендуется охватить как минимум четыре сценария:
- Приложение обнаруживает ожидаемое количество изображений и видео.
- После возврата из системного средства выбора тип файла, размеры в пикселях и продолжительность видео соответствуют ожидаемым значениям.
- Задача сжатия или отправки использует исходный ресурс, а не случайно полученное превью.
- Неподдерживаемые форматы, очень большие файлы и изменения разрешений приводят в чётко определённые ветви обработки ошибок.
simctl addmedia подходит для проверки цепочки чтения и обработки в симуляторе, но не заменяет тесты съёмки камерой, кодирования, специфичного для реальных устройств, и нагрузки на физическое хранилище. Если явно зафиксировать эти ограничения в описании тестов, сбой из-за ограничений симулятора не будет ошибочно принят за дефект продукта.
Цель регрессионного теста — не загрузить как можно больше материалов, а связать каждый файл с конкретным поведением, которое можно назвать, воспроизвести и диагностировать.
Подготовьте небольшие и стабильные медиафикстуры
Создайте в репозитории каталог Tests/Fixtures/Media и добавьте в него только минимальный набор файлов, необходимый для тестов. Имена файлов должны отражать их назначение, а не повторять автоматически созданные камерой названия.
| Файл | Назначение | Основная проверка |
|---|---|---|
portrait.jpg |
Вертикальное изображение с данными об ориентации | После коррекции ориентации ширина и высота указаны правильно |
transparent.png |
Изображение с альфа-каналом | После экспорта прозрачность сохранена |
short.mov |
Короткое видео | Продолжительность и тип медиа указаны правильно |
invalid.txt |
Файл, не являющийся медиафайлом | Этап добавления намеренно отклоняет файл |
Также храните список контрольных сумм SHA-256, чтобы графический редактор не мог незаметно перезаписать фикстуры:
cd Tests/Fixtures/Media
shasum -a 256 portrait.jpg transparent.png short.mov > SHA256SUMS
shasum -a 256 -c SHA256SUMS
Не перекодируйте фикстуры во время выполнения задания. Кодировщики в разных версиях системы могут записывать разные метаданные, и тогда проблема из категории «изменилось поведение приложения» перейдёт в категорию «изменились входные данные». Если динамически создаваемые файлы действительно необходимы, сохраняйте скрипт генерации, его параметры и контрольные суммы полученных файлов.
Изолируйте симулятор для каждого задания
В общем симуляторе, который используется длительное время, сохраняются ресурсы медиатеки, сведения о разрешениях и фоновые процессы. Самый простой базовый вариант — получить DEVICE_UDID от системы оркестрации, а в начале задания выключить и стереть симулятор, затем запустить его и дождаться завершения загрузки:
set -euo pipefail
: "${DEVICE_UDID:?DEVICE_UDID is required}"
: "${BUNDLE_ID:?BUNDLE_ID is required}"
xcrun simctl shutdown "$DEVICE_UDID" 2>/dev/null || true
xcrun simctl erase "$DEVICE_UDID"
xcrun simctl boot "$DEVICE_UDID"
xcrun simctl bootstatus "$DEVICE_UDID" -b
xcrun simctl privacy "$DEVICE_UDID" reset photos "$BUNDLE_ID" || true
xcrun simctl privacy "$DEVICE_UDID" grant photos "$BUNDLE_ID"
Модель симулятора и версию системы также необходимо зафиксировать в конфигурации задания. Нельзя ограничиваться параметром name=iPhone и позволять Xcode самостоятельно выбирать устройство. Параллельные задания должны использовать разные UDID, иначе одно из них может выполнить erase, пока другое ещё запускает тесты.
Проверки разрешений следует разделить на две группы. Для основного сценария заранее предоставьте доступ к медиатеке и проверяйте обработку медиа. Сценарий с отказом в доступе должен отдельно выполнять revoke и проверять только сообщение приложения и способ восстановления разрешения. Результат теста не должен зависеть от того, появилось ли системное диалоговое окно.
Добавьте материалы и запустите целевые тесты
Перед добавлением проверьте расширения и контрольные суммы, а затем одной командой передайте addmedia все поддерживаемые файлы:
FIXTURES="$PWD/Tests/Fixtures/Media"
shasum -a 256 -c "$FIXTURES/SHA256SUMS"
xcrun simctl addmedia "$DEVICE_UDID" \
"$FIXTURES/portrait.jpg" \
"$FIXTURES/transparent.png" \
"$FIXTURES/short.mov"
xcodebuild test \
-workspace Demo.xcworkspace \
-scheme Demo \
-destination "platform=iOS Simulator,id=$DEVICE_UDID" \
-only-testing:MediaImportTests \
-resultBundlePath "$PWD/Artifacts/MediaImport.xcresult"
Успешное завершение addmedia означает только то, что команда приняла файлы, но не гарантирует, что приложение уже видит нужные ресурсы. Тестовый код должен дождаться, пока запрос к медиатеке вернёт ожидаемое количество объектов, и использовать ограниченный тайм-аут. В проверках следует прежде всего учитывать тип медиа, размеры в пикселях, диапазон продолжительности и созданный бизнес-результат. Не полагайтесь на порядок отображения в системной медиатеке: время импорта может отличаться от времени создания ресурсов.
Если приложение отправляет файлы, сетевой слой можно заменить локальной тестовой реализацией, которая записывает полученный MIME-тип, количество байтов и контрольную сумму. Это позволит подтвердить, что приложение читает исходный ресурс, и не добавит в результаты регрессионных тестов нестабильность внешней сети.
Сохраняйте данные для повторного анализа сбоев
Для завершившегося сбоем задания необходимо сохранить как минимум три вида данных: xcresult, контрольные суммы фикстур и сведения об использованном устройстве. Дополнительно можно вывести список доступных симуляторов, но не следует собирать содержимое пользовательских каталогов, не относящееся к проблеме.
Распространённые ошибочные выводы и способы их устранения:
- Ресурсов больше, чем ожидалось: симулятор не был стёрт перед заданием либо несколько заданий использовали один UDID.
- Тест иногда не находит видео: запрос выполняется сразу после импорта, без ожидания завершения обновления медиатеки.
- Ширина и высота изображения перепутаны: при чтении размеров в пикселях код игнорирует метаданные ориентации.
- Локально тест проходит, а в CI завершается сбоем: тест зависит от файлов, не добавленных в репозиторий, разрешений по умолчанию или неоднозначного параметра destination.
- Контрольная сумма отправляемого файла меняется: приложение перекодирует ресурс; контрольные суммы исходных данных и тела отправляемого запроса следует записывать отдельно.
По завершении задания выключите симулятор. Если устройство было временно создано текущим заданием, сразу удалите его. Даже постоянные устройства следует снова очищать командой erase перед следующим заданием, а не полагаться на поэлементное удаление содержимого медиатеки. Итоговый контрольный список можно свести к следующим пунктам: контрольные суммы фикстур совпадают, UDID используется только одним заданием, версия системы зафиксирована, состояние разрешений задано явно, тест умеет ждать появления ожидаемого количества импортированных объектов, а пакет результатов сохранён в архиве. При соблюдении этих условий сбой импорта медиа будет воспроизводиться на стабильных входных данных, а сохранённых материалов хватит для повторного анализа.
Часто задаваемые вопросы
Может ли simctl addmedia полностью заменить тесты на устройстве?
Нет. Он подходит для проверки библиотеки, выбора и чтения файлов в симуляторе, но камеру, аппаратные кодеки и поведение при реальном дефиците хранилища нужно проверять на устройстве.
Как исключить накопление файлов между запусками CI?
Выделяйте отдельный симулятор для каждой задачи, перед загрузкой выполняйте shutdown и erase, а после теста удаляйте временное устройство.
Запустите следующую сборку на выделенном физическом узле Apple Silicon
Выберите срок аренды и регион узла, проверьте Mac Mini M4, 16 ГБ RAM, SSD 256 ГБ и сумму к оплате в USD, затем оформите заказ.