Тестирование программного обеспечения в наши дни стало неотъемлемой частью процесса разработки программного обеспечения во всем мире. Уже не найти ни одного серьезного проекта без покрытия, хотя-бы Unit-тестами. Существуют различные техники и подходы к тестированию. Кто-то покрывает тестами уже написанный код, кто-то использует тестирование как инструмент для добавления новой функциональности (разработка через тестирование). В обоих случаях время, затраченное на тестирование кода, включается в общие затраты по разработке. И чем больше и сложнее проект, тем большее время тратится для выполнения всех тестов. Как оптимизировать затраты на тестирование? Существует несколько путей оптимизации процесса тестирования продукта. От рефакторинга тестов и тестовых данных, до увеличения мощностей оборудования. Рефакторинг и оптимизированный запуск разных групп тестовых заданий действительно может сократить время общего прогона тестов, но в конечном итоге встает вопрос вертикального масштабирования, если ресурсов не хватает, а выкладывать в production очередной релиз без проверки всех тестовых заданий никак нельзя. Вопрос становится еще сложнее, если этот процесс еще не автоматизирован. Одно из возможных решений сокращения затрат времени на запуск тестов - распараллеливание тестовых задач и максимальная нагрузка всех ресурсов тестового оборудования. Рассмотрим в качестве примера простое Web-приложение на RubyOnRails. Весь комплекс тестов по-умолчанию делится на
- тестирование контроллеров
- тестирование моделей
- тестирование “хелперов”
- тестирование роутинга
- тестирование представлений
- интеграционное тестирование
По-умолчанию, в Rails с помощью одной командой rake test
или rake spec
происходит запуск всех тестов в соотвествующих папках (test или spec).
Пока проект небольшой, команды очень редко задумываются об распараллеливании этих задач. Многие тестовые среды и сервисы этого даже не поддерживают. С помощью Vexor мы имеем возможность распараллелить задачи тестирования. И вот как это работает. Сервис предоставляет возможность запуска сразу нескольких задач одновременно с помощью матрицы заданий. Эти задания запускаются одновременно, используя все вычислительные ресурсы.
Рассматриваемый нами фреймворк Rails группирует все тесты по различным типам, помогающим проводить тестирование.
rake test:controllers # Запускает все тесты контроллеров из test/controllers
rake test:functionals # Запускает все функциональные тесты из test/controllers, test/mailers и test/functional
rake test:helpers # Запускает все тесты хелперов из test/helpers
rake test:integration # Запускает все интеграционные тесты из test/integration
... и т.д.
Как мы можем видеть, Rails предоставляет четкое разделение тестов на группы, и мы можем этим воспользоваться. Добавим запуск каждой группы тестов в файл конфигурации vexor.yml
:
env:
global:
- RAILS_ENV=test
matrix:
- BUILD_CMD="bundle exec rake test:controllers"
- BUILD_CMD="bundle exec rake test:functionals"
- BUILD_CMD="bundle exec rake test:helpers"
- BUILD_CMD="bundle exec rake test:integration"
А затем, настроим запуск выполняемого динмаического скрипта одной командой там же в файле vexor.yml
:
script: bundle exec ${BUILD_CMD}
VexorCI запустит на выполнение эти 4 задания одновременно. Общее время, затраченное на выполнение тестов будет равно времени выполнения самой долгой задачи.
Если в Вашем проекте уже подключены библиотеки распараллеливания тестов, такие как parallel_rspec
, то можно использовать встроенную поддержку этой библиотеки прямо в VexorCI. Для этого достаточно в файле настроек указать количество параллельных заданий для этой библиотеки и в качестве скрипта выполнения указать следующие значения:
parallel: 4
script: parallel_rspec
VexorCI сам настроит выполнение тестов согласно настройке библиотеки, отпимально распределив нагрузку на ресурсы и очередность выполнения тестов.
Кроме запуска тестов, хорошей практикой является запуск дополнительных продуктов, проверяющих правильность написания кода, различные сканеры уязвимостей и соответствие кода принятым стандартам. Для Ruby
есть сразу несколько подобных инструментов. Наиболее популярными является Brakeman и Rubocop. На подобные проверки также требуется некоторое время. И эти затраты также можно оптимизировать с помощью мартицы выполнения задач VexorCI.
Добавляем эти проверки в список martix
конфигурационного файла vexor.yml
параллельно с задачами запуска тестов.
env:
matrix:
- BUILD_CMD="bundle exec rake test:controllers"
- BUILD_CMD="bundle exec rake test:functionals"
- BUILD_CMD="bundle exec rake test:helpers"
- BUILD_CMD="bundle exec rake test:integration"
- BUILD_CMD="bundle exec brakeman"
- BUILD_CMD="bundle exec rubocop"
И сокращаем время полного тестирования системы еще на несколько единиц времени.