Как я могу выполнить тесты на RoR быстрее? - PullRequest
5 голосов
/ 05 июля 2011

Я использую Ruby on Rails 3 и пишу тесты, но это слишком медленно.Есть ли хорошие настройки или инструменты, чтобы сделать это быстрее?

Ответы [ 5 ]

4 голосов
/ 05 июля 2011

Вероятно, наибольшее увеличение скорости происходит из-за того, что вы не попали в базу данных, если вам не нужно. Смоделируйте объекты, а не извлекайте их из базы данных и / или (если вы, например, используете Factory Girl), используйте Factory.build (: stuff) вместо Factory (: stuff), где это возможно. Только после того, как вы это сделаете, вам следует начать дальнейшую оптимизацию с помощью spork

Обновление: Лично я тоже начинаю думать, что вам все равно не стоит зацикливаться на скорости ваших тестов. Очевидно, что чем быстрее, тем лучше, но по мере роста приложения набор тестов будет расти, и, как бы вы ни были осторожны, он в конечном итоге станет медленнее, чем хотелось бы. Я все больше и больше полагаюсь на гем самоиспытаний, который тестирует изменение кода и работает в фоновом режиме (guard-rspec выполняет аналогичную работу). К тому времени, когда ваше приложение достигнет 1000 тестов, вам не нужно будет ждать завершения всего пакета каждый раз, когда вы вносите изменения, какими бы быстрыми ни были тесты.

2 голосов
/ 08 июля 2011

ИМХО основной замедляющей частью тестирования является конфигурация приборов по умолчанию.Если ваша конфигурация (в test/test_helper.rb):

class ActiveSupport::TestCase
  self.use_transactional_fixtures = false
  self.pre_loaded_fixtures = false
  self.use_instantiated_fixtures  = true

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

Если вы измените настройки на противоположные:

class ActiveSupport::TestCase
  self.use_transactional_fixtures = true
  self.pre_loaded_fixtures = true
  self.use_instantiated_fixtures  = false

, тогда база данных будет воссоздана только один раз для каждого тестового файла, и вы загрузите только те записи, которые вам действительно нужны вкаждый метод тестирования.

Это зависит от размера вашего набора данных тестирования, считаете ли вы приемлемым время создания тестовой базы данных.Когда у меня был довольно большой набор тестовых данных, я загружал приборы только один раз, перед всем набором тестов, но этот проект был (есть) в Rails 1, и я сильно изменил его, поэтому не могу сказать, как это сделатьв Rails 3 (по крайней мере, до тех пор, пока проблема не станет болезненной в каком-то новом проекте;).

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

2 голосов
/ 05 июля 2011

Как говорит @eml, если вы используете RSpec, вы можете использовать Spork. Это в основном запускает среду (которая является медленной частью), а затем сохраняет ее, разветвляясь каждый раз, когда вы запускаете свои спецификации.

Для более общего решения проблемы «среда всегда загружена» можно установить rails-sh и запустить свои тесты из оболочки.

Примечание: Ruby 1.9.3 должен немного облегчить эту проблему, поскольку оптимизировано требуемое время.

0 голосов
/ 06 мая 2012

Постарайтесь разработать так, чтобы большинство ваших тестов можно было выполнять без загрузки всей инфраструктуры приложений Rails. В вашем помощнике по спецификациям пропустите загрузку окружения или rpec / rails, если выполняются только быстрые тесты, что-то вроде ...

# /spec/spec_helper.rb
if RSpec.configuration.inclusion_filter[:fast]
  # Setup required for fast tests in particular (if any)
  # ...
else
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'

  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
end

RSpec.configure do |config|
  # ...

  unless RSpec.configuration.inclusion_filter[:fast]
    # If you're not using ActiveRecord, or you'd prefer not to run each of your
    # examples within a transaction, remove the following line or assign false
    # instead of true.
    config.use_transactional_fixtures = true
  end
end

Чтобы пометить тест как «быстрый», добавьте параметр , :fast => true к его вызову it или к окружающему вызову describe.

Чтобы запустить только быстрые тесты, выполните rspec --tag fast из командной оболочки.

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

Одна хитрость в моем арсенале состоит в том, чтобы избегать непосредственного написания кода для модели ActiveRecord или другого такого класса, и вместо этого предпочесть писать его в модуле mixin. Вы можете протестировать модуль mixin, определив Subject как объект, который расширяется этим модулем ...

describe 'MyModule', :fast => true
  subject{ Object.new.tap{|o| o.extend MyModule} }

  it 'does something' do
    # ...
  end
end
0 голосов
/ 06 мая 2012

Я рекомендую Spork и Guard, они оба могут отлично работать с RSpec.

Spork может помочь вам быстрее выполнять тесты, http://railscasts.com/episodes/285-spork

Guard может помочь вам запускать тесты автоматически. http://railscasts.com/episodes/264-guard

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...