Оглавление
Параллельный запуск тестов является одним из самых простых и эффективных способов экономии времени (спасибо, кэп). Но в этой статье речь пойдет не о запуске тестов в нескольких потоках на одной машине и с использованием разных баз данных для каждого потока. Такой подход применяется в parallel_tests. Мы рассмотрим другой кейс. А именно — способ параллельного запуска тестов на нескольких CI нодах, основанный на времени выполнения тестов в каждом отдельном файле.
Для того чтобы реализовать задуманное нам понадобится gem Knapsack.
Принцип работы Knapsack
Изначально мы запускаем билд на CI, в процессе выполнения которого Knapsack генерирует отчет. Отчет состоит из списка файлов, которые содержат тесты. А также времени выполнения каждого из них.
При следующем запуске указывается количество нод, используемых для запуска и номер ноды, на которой вы хотите запустить билд. На основании переданных параметров и имеющегося отчета, Knapsack формирует список файлов, запускаемых на выбранной ноде.
Одна из исключительных особенностей Knapsack заключается в том, что он балансирует объем запускаемых тестов таким образом, что время выполнения билда на каждой из нод будет приблизительно одинаковым. Тут возникает вопрос: как часто следует создавать новый отчет для того чтобы гем балансировал время выполнения задачи оптимальным способом. Здесь нам на помощь приходит документация. Там сказано, что необходимость создания нового отчета возникает только в тот момент, когда на проекте появляются новые долгие тесты.
Пункты из документации, которым стоит уделить особое внимание:
Knapsack: типы уведомлений
Гем Knapsack имеет несколько типов уведомлений пользователей. Давайте разберем основные.
Knapsack time offset warning:
Это уведомление появляется в случае, если время выполнения билда отличается от ожидаемого максимума в большую сторону. Предположим, что время, рассчитанное на основе отчета, должно равняться 10 минутам. Вы запускаете его на 4 нодах. Knapsack по умолчанию предполагает, что погрешность при выполнении (Time offset) будет равна 30 секундам. Таким образом, максимальное время выполнения билда на одной ноде должно быть не больше 3 минут. Появление этого уведомления может указывать на то, что вам необходимо пересоздать отчет. Более детально — здесь.
Leftover specs:
При запуске тестов, вы можете заметить в логах раздел Leftover Specs, который содержит список файлов. В этот список включены файлы, для которых в отчете не прописано время выполнения. Каковы причины? Либо тестовый файл пустой, либо он был создан после генерации отчета. Если количество таких файлов велико, возможно вам стоит переделать отчет.
Настройка Knapsack на CI
Настройка Knapsack на CI вполне тривиальна и довольно подробно описана в документации. Мы же рассмотрим немного более гибкий вариант, применяемый разработчиками Gitlab для запуска своих билдов. Этот принцип мы использовали на одном из своих проектов (NameCoach).
Речь пойдет о настройке Gitlab CI.
*Необходимость в реализации данного решения для Drone CI пока не оправдывает то время, которое может для этого потребоваться, в силу топорности самого Drone CI. Поэтому, на данном этапе, мы используем стандартный флоу с одним отчетом, который время от времени обновляется одним из разработчиков.
Итак, что для этого нужно предпринять:
- Проверка наличия файла с отчетом и его создание в случае необходимости
- Запуск билдов на нескольких нодах с опцией создания отчета и путем к кастомному отчету для каждой отдельной ноды
- Объединение всех «мини-отчетов» в полноценный отчет и сохранение его в артефактах для следующего билда.
Чем хорош такой подход?
Нам не нужно хранить отчет в репозитории. Мы всегда имеем самую свежую версию отчета (именно на нее полагается Knapsack). А в случае появления новых долгих тестов, которые отсутствуют в отчете и которые однозначно нарушат баланс в сторону одной из нод, мы получим оптимальный отчет уже на втором билде. А далее уже сбалансируем время выполнения тестов на всех нодах.
Теперь мы вам покажем, как это выглядит. Обратите внимание, что мы используем три разных steg`a для каждого из описанных шагов. Stages выполняются синхронно, в указанном порядке. А билды внутри одного stag`a выполняются параллельно.
Ниже представлен код исполняемого файла, который используется для объединения отдельных отчетов в один. Вам просто необходимо создать в папке bin файл merge-reports (не забудьте сделать его исполняемым c помощью команды chmod +x bin/merge-reports).
+
Вывод
Время, затраченное на внедрение данного инструмента, оправдало себя с головой. Нам удалось добиться более чем двукратного сокращения времени прохождения билда.
До внедрения билды были настроены следующим образом: unit тесты — отдельно, feature тесты -отдельно. Использовался принцип —fail-fast для того чтобы билд падал уже после первого провалившегося теста. Время всего билда составляло ~50 минут (к тому же билд частенько падал из-за высокой нагрузки)
Лучшее время, которое было отмечено после внедрения Knapsack ~18 минут. В среднем билд занимает 22-28 минут (для сравнения: локально этот билд идет ~13-14 минут на MacBook Pro mid 2014).