- UI-тесты могут выполняться 40 минут
- Что такое шардинг
- Встроенная параллелизация
- Балансировка шардов
- Flank
- Ускорение на 40%
- Еще плюсы
- Внедрение в CI
Проблемы с UI
“Каждый Android-разработчик бывал в такой ситуации: ты загружаешь код, запускаешь CI-конвейер, а затем… ждешь. И ждешь. И ждешь еще. Только чтобы узнать, прошли ли UI-тесты. Как-то пришлось ждать 40 минут.
В прошлом месяце я столкнулся именно с этой проблемой. UI-тесты разбухли так, что на их выполнение на CI-сервере уходил почти час. Хуже того, иногда они вылетали, оставляя нас без фидбека. Цикл разработки останавливался.
Тогда я узнал, что такое шардинг тестов.
Что такое шардинг тестов
Это простая и мощная концепция: вместо последовательного выполнения UI-тестов на одном устройстве вы распределяете их на несколько виртуальных устройств, выполняющих тесты параллельно. Задача выполняется гораздо быстрее, и вы получаете фидбек быстрее.
Для Android-разработчиков это означает:
- Ускорение сборки в CI
- Ускорение цикла фидбека
- Больше тестирования без длительных пауз
- Повышение производительности разработчиков.
Встроенная параллелизация
Firebase Test Lab от Google поддерживает шардинг “из коробки”. Не нужна сложная инфраструктура или кастомные решения — достаточно прописать в командной строке, сколько шардов вам нужно.
Пример, как запустить простой тест с шардированием:
gcloud beta firebase test android run \ --app=app-debug.apk \ --test=app-debug-androidTest.apk \ --device=model=Pixel3,version=30 \ --num-uniform-shards=5
Эта команда параллельного запуска тестов на 5 шардах. Под капотом FTL самостоятельно распределяет тест-кейсы по этим шардам.
Если хочется попробовать, то прежде чем включать шардинг с помощью gcloud, можно включить шардинг тестов в консоли Firebase.
Балансировка шардов
При реализации своего решения я столкнулся с интересным ограничением: количество шардов должно быть меньше или равно количеству тест-кейсов. Если подумать, это вполне логично.
Но есть и другая, более тонкая проблема. Если у вас 20 тест-кейсов и 5 шардов, то каждый шард получит по 4 теста. Но что, если одни тесты занимают 10 секунд, а другие — 2 минуты? В итоге вы получите “несбалансированные” шарды, и ваш тест будет по-прежнему зависеть от самого медленного шарда.
Здесь должен помочь Flank
Инструмент с открытым кодом, который работает поверх Firebase Test Lab, оптимизируя распределение тестов по шардам. Вместо того чтобы тупо распределять тесты поровну, Flank анализирует предыдущие прогоны и принимает смарт-решения, по каким шардам распределить тесты.
Для настройки Flank нужен конфиг-файл следующего вида:
gcloud: app: app-debug.apk test: app-androidTest.apk device: - model: Pixel_3 version: 30 use-orchestrator: true timeout: 30m flank: max-test-shards: 5 shard-time: 120 smart-flank-gcs-path: gs://your-bucket-path
Волшебство происходит благодаря параметру smart-flank-gcs-path
, который указывает Flank, где хранить и откуда извлекать зафиксированное время выполнения прошлых тестов. С помощью этих данных Flank распределяет тесты, создавая сбалансированные шарды без узких мест.
Результат: выполнение на 40 % быстрее
После интеграции Flank в CI-конвейер результаты впечатлили. Время выполнения наших UI-тестов сократилось примерно на 40% — с 40 с лишним минут до 24 минут.
Когда Flank работает с 5 шардами, Firebase Test Lab запускает 5 виртуальных устройств для параллельного выполнения тестов. Однако в консоли Firebase вы по-прежнему видите только один тест — потому что FTL абстрагируется от деталей распараллеливания.
Каждый шард берет тесты из JSON-файла, сгенерированного Flank, сопоставляя тесты с шардами. Когда шард заканчивает выполнение назначенных ему тестов, он может взять из очереди еще несколько, обеспечивая эффективное распределение ресурсов.
Еще плюсы
Помимо скорости, я обнаружил еще несколько преимуществ такого подхода:
- Повышение стабильности тестов: благодаря сокращению циклов тестирования мы снизили вероятность таймаутов и сбоев, связанных с сетью.
- Эффективное использование ресурсов: наши ресурсы CI использовались более эффективно, что позволило выполнять больше параллельных задач.
- Обнаружение нестабильных тестов: Flank может автоматически перезапускать падающие тесты, повышая их надежность.
- Подробная отчетность: мы получили более полное представление о том, какие тесты самые медленные.
Внедрение в CI-конвейер
Если вы столкнулись с подобными задержками при тестировании пользовательского интерфейса, вот как реализовать это решение:
- Установите Flank: добавьте его в свой проект или на CI-сервер.
- Создайте файл конфигурации: настройте flank.yml с соответствующими параметрами.
- Обновите workflow в CI: измените конфигурацию CI, чтобы использовать Flank вместо прямых вызовов FTL.
- Мониторинг и подстройка: начните с умеренного количества шардов и корректируйте его в зависимости от полученных результатов.
Для команд, использующих Bitrise, можно добавить кастомный шаг сценария, например, такой:
$ curl -sL https://github.com/Flank/flank/releases/download/v23.10.1/flank.jar -o flank.jar $ java -jar ./flank.jar firebase test android run
Заключение
Внедрение шардинга тестов с помощью Flank и Firebase Test Lab изменило наш процесс разработки. Сокращение времени выполнения UI-тестов на 40% дало ускорение циклов фидбека, удовлетворение разработчиков и в конечном счете более качественный продукт.
Если у вас медленные UI-тесты в Android-проектах, я настоятельно рекомендую попробовать этот подход. Настройка простая, а выгода мгновенная.”