Воспроизводимый тест импорта медиа iOS через simctl addmedia

DevOps и CI/CD ·~5 мин чтения

Воспроизводимый тест импорта медиа iOS через simctl addmedia

После выбора изображения из медиатеки приложению может потребоваться прочитать данные об ориентации, создать миниатюру, сжать исходный файл и отправить его. При работе с видео дополнительно появляются ветви, связанные с продолжительностью, кодеком и размером файла. Однократная ручная проверка на компьютере разработчика не доказывает, что следующая сборка сможет обработать тот же набор входных данных. Более надёжный подход — хранить медиафайлы в репозитории как тестовые фикстуры, сбрасывать отдельный симулятор на удалённом Mac и добавлять материалы в его медиатеку с помощью simctl addmedia.

Сначала определите границы проверки

Такие тесты должны проверять интерфейс между приложением и системной медиатекой, а не автоматизировать приложение «Фото». Рекомендуется охватить как минимум четыре сценария:

  1. Приложение обнаруживает ожидаемое количество изображений и видео.
  2. После возврата из системного средства выбора тип файла, размеры в пикселях и продолжительность видео соответствуют ожидаемым значениям.
  3. Задача сжатия или отправки использует исходный ресурс, а не случайно полученное превью.
  4. Неподдерживаемые форматы, очень большие файлы и изменения разрешений приводят в чётко определённые ветви обработки ошибок.

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, контрольные суммы фикстур и сведения об использованном устройстве. Дополнительно можно вывести список доступных симуляторов, но не следует собирать содержимое пользовательских каталогов, не относящееся к проблеме.

Распространённые ошибочные выводы и способы их устранения:

По завершении задания выключите симулятор. Если устройство было временно создано текущим заданием, сразу удалите его. Даже постоянные устройства следует снова очищать командой erase перед следующим заданием, а не полагаться на поэлементное удаление содержимого медиатеки. Итоговый контрольный список можно свести к следующим пунктам: контрольные суммы фикстур совпадают, UDID используется только одним заданием, версия системы зафиксирована, состояние разрешений задано явно, тест умеет ждать появления ожидаемого количества импортированных объектов, а пакет результатов сохранён в архиве. При соблюдении этих условий сбой импорта медиа будет воспроизводиться на стабильных входных данных, а сохранённых материалов хватит для повторного анализа.

Часто задаваемые вопросы

Может ли simctl addmedia полностью заменить тесты на устройстве?

Нет. Он подходит для проверки библиотеки, выбора и чтения файлов в симуляторе, но камеру, аппаратные кодеки и поведение при реальном дефиците хранилища нужно проверять на устройстве.

Как исключить накопление файлов между запусками CI?

Выделяйте отдельный симулятор для каждой задачи, перед загрузкой выполняйте shutdown и erase, а после теста удаляйте временное устройство.

Debug M4

Запустите следующую сборку на выделенном физическом узле Apple Silicon

Выберите срок аренды и регион узла, проверьте Mac Mini M4, 16 ГБ RAM, SSD 256 ГБ и сумму к оплате в USD, затем оформите заказ.

Арендовать облачный Mac