Pull to refresh

Распараллеливание тестов или одна голова — хорошо, а две головы — лучше

IT systems testing *
В какой-то момент, если долго и усердно стараться сохранять покрытие тестами не меньше 80% кода, прогон полного комплекта тестов начнет занимать больше времени, чем уходит на перекур и на прочтение новых статей хабра. В свою очередь это приводит к тому, что полный комплект (suite) будет запускаться все реже и реже. Hudson начнет сообщать о сломанных билдах, а дальше сработает эффект разбитого окна и сломанный билд станет нормой.

Можно стараться запускать полный прогон перед каждым коммитом. Но затраты времени на кино в виде пробегающих по экрану фич cucumberа, а также выход из потока снизят эффективность разработчиков в разы.

В одном из наших проектов, в который согласно записям redmine вложено около 400 часов работы нашего коллектива ситуация с тестами до распараллеливания выглядела так (пару дней назад):
151 scenarios (151 passed)
3997 steps (3997 passed)
17m49.257s


18 минут!!!

За это время разработчик может сварить кофе, выкурить сигарету, сходит в туалет, ущипнуть за попу симпатичную коллегу и успеть посмотреть последние 3 минуты «матрицы» на экране. Если требовать от него чтобы полный прогон запускался перед каждым коммитом, то он только и будет делать что смотреть «матрицу» и щипать попы пить кофе.

Но анализ загрузки процессора при прогоне показывает, что в работе участвует только лишь одно ядро независимо от того, сколько их всего есть. Как говорит пословица, лучше день потерять, а потом за пять минут долететь. Порыскав в гугле мы нашли гем parallel_tests. Теперь мы не с такой завистью будем смотреть на erlang группу, которые могут спокойно распараллелить свои тесты на кластер арендованных облачных машин в Selectel.

Гем parallel_tests по сравнению с аналогами (hydra, testjour) выделяется тем, что дает возможность распараллелить именно любимые нами интеграционные тесты на cucumber+capybara+selenium-webdriver, которые из-за обильной аяксификации нашего приложения нельзя выполнить без реального браузера, иными словами — запущенного через гем capybara firefox. При этом реально запускаются несколько копий firefox, на которые более-менее равномерно распределяется нагрузка. htop при этом демонстрирует полную загрузку всех ядер, сколько бы их не было на машине. И, что играет немалую роль, адаптировать приложение для использования этого гема очень просто.

Во-первых, надо обеспечить существование нескольких тестовых баз, по одной на ядро в типовом случае. Гем сам устанавливает при запуске переменную окружения TEST_ENV_NUMBER, поэтому в database.yml можно прописать в разделе test
test:
database: xxx_test<%= ENV['TEST_ENV_NUMBER'] %>

Естественно, базы надо перед прогоном создать руками или через
rake parallel:create


Во-вторых, надо обеспечить синхронизацию схем баз данных при проведении дополнительных миграций или перепроведении старых:
rake parallel:prepare


В-третьих, запускать прогон надо по-другому
rake parallel:features

Это — для прогона фич cucumber. Можно и rspec и обычные рельсовые тесты гонять.

Да, гем, конечно же, надо прописать в Gemfile и поставить
bundle install


Как результат — вот результаты последней сборки хадсоном на восьмиядерном селектеловском ксеончеге
Results:
17 scenarios (17 passed)
347 steps (347 passed)
31 scenarios (31 passed)
780 steps (780 passed)
8 scenarios (8 passed)
149 steps (149 passed)
26 scenarios (26 passed)
1363 steps (1363 passed)
26 scenarios (26 passed)
463 steps (463 passed)
17 scenarios (17 passed)
331 steps (331 passed)
6 scenarios (6 passed)
88 steps (88 passed)
19 scenarios (19 passed)
410 steps (410 passed)

Took 338.989782947 seconds
Finished: SUCCESS


Да, мы уменьшили количество шагов и сценариев, потому что кроме использования параллелизации, код тестов претерпел некий рефакторинг. Но 150 против 151 — не сильно меньше. Зато по времени — 5 с половиной минут против почти 18. Это еще с учетом примерно 60-70 секунд константных затрат на свежий pull из репозитория, перемиграцию баз и запуск файрфоксов.

Результат налицо, а как следствие, всего за сутки билд в хадсоне застабилизировался — 5 последних коммитов успешно отработали по полному комплекту тестов, чего и всем желаю.

UPD: Если в параллельном режиме не обнаруживаются step_definitions решение нашел хабрачеловек Alder. Тогда надо запускать тесты так:
parallel:features[2,'','--require features']
Tags:
Hubs:
Total votes 38: ↑38 and ↓0 +38
Views 4.6K
Comments Comments 38