Ускорение тестов RSpec в приложении Rails

У меня есть приложение Rails с более чем 2000 примерами в тестах RSpec. Излишне говорить, что это большое приложение, и там много нужно протестировать. Запуск этих тестов на данный момент очень неэффективен, и поскольку он занимает очень много времени, мы почти не можем его написать, прежде чем нажимать новую сборку. Я добавил --profile к моим spec.opts, чтобы найти самые длинные запущенные примеры, и по меньшей мере 10 из них занимают в среднем 10 секунд для запуска. Это нормально среди вас специалистов RSpec? Для одного примера длится 10 секунд? Я понимаю, что с 2000 примерами потребуется не тривиальное количество времени, чтобы тщательно протестировать все, но в этот момент 4 часа немного смехотворно.

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

Ответ 1

10 секунд - это очень длительное время для запуска любого одного теста. Чувство моего кишечника заключается в том, что ваша целевая цель одновременно выполняет как единичные, так и интеграционные тесты. Это типичная вещь, в которой проекты вступают и на каком-то этапе вам нужно будет преодолеть этот технический долг, если вы хотите производить больше, быстрее. Существует несколько стратегий, которые могут помочь вам сделать это... и я порекомендую несколько, которые я использовал в прошлом.

1. Отдельный блок из тестов интеграции

Первое, что я хотел бы сделать, это отделить блок от тестов интеграции. Вы можете сделать это либо:

  • Перемещение их (в отдельные папки в каталоге спецификаций) - и изменение целей рейка
  • Пометка тегов (rspec позволяет пометить ваши тесты)

Философия гласит, что вы хотите, чтобы ваши регулярные сборки были быстрыми, иначе люди не будут слишком счастливы запускать их часто. Так что вернитесь на эту территорию. Получите регулярные тесты для быстрого запуска и используйте сервер непрерывной интеграции для запуска более полной сборки.

Тест интеграции - это тест, который связан с внешними зависимостями (например, Database, WebService, Queue, а некоторые будут аргументировать FileSystem). A unit test просто проверяет определенный элемент кода, который вы хотите проверить. Он должен работать быстро (возможно 9000 через 45 секунд), т.е. Большая часть из них должна работать в памяти.

2. Преобразование тестов интеграции в тесты единиц

Если основная часть ваших модульных тестов меньше, чем у пакета интеграции, у вас есть проблема. Это означает, что несогласования начнут появляться более легко. Поэтому отсюда приступайте к созданию дополнительных модульных тестов для замены интеграционных тестов. Что вы можете сделать, чтобы помочь в этом процессе:

  • Используйте фальшивую инфраструктуру вместо реального ресурса. Rspec имеет встроенную насмешливую структуру.
  • Запустите rcov в вашем пакете unit test. Используйте это, чтобы оценить, насколько полно ваш пакет unit test.

Как только у вас есть правильный unit test для замены теста интеграции - удалите тест интеграции. Повторное тестирование только ухудшает обслуживание.

3. Не использовать светильники

Светы злые. Вместо этого используйте factory (машинист или factory_girl). Эти системы могут создавать более адаптируемые графики данных, и, что более важно, они могут создавать объекты памяти, которые вы можете использовать, а не загружать вещи из внешнего источника данных.

4. Добавление проверок для остановки тестирования модулей. Станьте тестами интеграции

Теперь, когда у вас есть более быстрое тестирование, время, чтобы поставить проверки, чтобы остановить это от повторения.

Существуют библиотеки, в которых активная запись патчей обезьян бросает ошибку при попытке доступа к базе данных (UnitRecord).

Вы также можете попробовать спаривание и TDD, которые могут помочь заставить вашу команду писать более быстрые тесты, потому что:

  • Кто-то проверяет - так никто не ленится
  • Соответствующая TDD требует быстрой обратной связи. Медленные тесты просто делают все это болезненным.

5. Использование других библиотек для преодоления проблемы

Кто-то упомянул spork (ускоряет время загрузки тестового набора под rails3), hydra/parallel_tests - параллельно запускает параллельные тесты (через несколько ядер).

Это, вероятно, следует использовать LAST. Ваша настоящая проблема на первом шаге 1, 2, 3. Решите эту проблему, и вы сможете лучше расположить дополнительную инфраструктуру.

Ответ 2

Для отличной поваренной книги по повышению производительности вашего тестового набора ознакомьтесь с презентацией Grease Your Suite.

Он документирует 45-кратное ускорение во время выполнения тестового набора, используя такие методы, как:

Ответ 3

Вы можете использовать Spork. Он имеет поддержку 2.3.x,

https://github.com/sporkrb/spork

или./script/spec_server, который может работать для 2.x

Также вы можете редактировать конфигурацию базы данных (что существенно ускоряет запросы к базе данных и т.д.), что также повысит производительность для тестов.

Ответ 4

10 секунд на пример кажется очень длинным. Я никогда не видел спецификации, которая занимала более одной секунды, и большинство из них занимают гораздо меньше. Вы тестируете сетевые подключения? База данных пишет? Файловая система пишет?

Используйте mocks и stubs как можно больше - они намного быстрее, чем писать код, который попадает в базу данных. К сожалению, издевательство и укутывание также требуют больше времени для написания (и сложнее сделать правильно). Вы должны сбалансировать время, затрачиваемое на тестирование, и время, затрачиваемое на тестирование.

I второй Андрей Гримм комментарий о поиске в системе CI, которая может позволить вам распараллелить ваш набор тестов. Для чего-то такого размера это может быть единственным жизнеспособным решением.

Ответ 6

Несколько человек упомянули Гидру выше. Мы использовали его с большим успехом в прошлом. Недавно я документировал процесс получения гидры: http://logicalfriday.com/2011/05/18/faster-rails-tests-with-hydra/

Я согласен с тем, что этот метод не должен использоваться в качестве замены для написания тестов, которые хорошо структурированы и быстро по умолчанию.

Ответ 8

quick_require gem может вам помочь. Кроме того, ваш единственный способ - профиль (как и вы) - оптимизировать или использовать spork или что-то, что запускает ваши спецификации параллельно для вас. http://ruby-toolbox.com/categories/distributed_testing.html

Ответ 10

Здесь есть очень общее видео по улучшению скорости тестирования. Может помочь.

Ответ 11

Вы можете выполнить несколько простых советов, чтобы сначала исследовать, где большая часть времени проводится, если вы еще не пробовали их. Посмотрите на следующую статью:

https://blog.mavenhive.in/7-tips-to-speed-up-your-webdriver-tests-4f4d043ad581

Я думаю, что большинство из них - это общие шаги, которые будут применяться независимо от инструмента, используемого для тестирования.

Ответ 12

Удалить существующий набор тестов. Будет невероятно эффективно.