Rspec, Cucumber: лучшая скорость базы данных.
Я хотел бы увеличить скорость моих тестов.
- Должен ли я использовать
use_transactional_fixtures
или идти с камнем database_cleaner
?
- Какая стратегия database_cleaner лучше? Я заметил, что после перехода от
:truncation
до :transaction
мои более 800 примеров выполняются примерно в 4 раза быстрее!
- Должен ли я отключить
use_transactional_fixtures
, когда я использую database_cleaner :transaction
?
- Верно ли, что наилучшей стратегией для rack_test является
:transaction
?
- Каковы наилучшие методы для изменения стратегии "на лету" от
:transaction
до :truncation
при использовании селена или akephalos?
P.S. Mysql, Rails 3, Rspec2, огурец
P.P.S. Я знаю о spork и parallel_test и используя их. Но они оффтопичны. Например, Spork экономит около 15-20 секунд при запуске всего пакета, но изменение от :transaction
до :truncation
резко увеличивает время работы от 3,5 до 13,5 минут (разница в 10 минут).
Ответы
Ответ 1
1., 2. и 4... Если вы используете двигатель по умолчанию capybara, rack_test, вы должны использовать транзакции (либо с поддержкой use_transactional_fixtures
, либо поддержкой транзакций из драгоценного камня database_cleaner). Как вы отметили, использование транзакций значительно быстрее, чем использование стратегии усечения. Однако, когда записи базы данных могут проходить через разные потоки (как с селеном), транзакции не будут работать. Таким образом, вам нужно будет использовать усечение (или заставить все переходить через один поток db - другой вариант).
3. Да, вы должны отключить use_transactional_fixtures
при использовании драгоценного камня database_cleaner, поскольку драгоценный камень поддерживает транзакции. Если вам нужны транзакции, просто используйте use_transactional_fixtures и никогда не загружайте драгоценный камень database_cleaner.
5. Следующий код будет переключаться между :transaction
и :truncation
на лету. (Протестировано с помощью rspec, capybara, rails3.)
Особенности. Это должно дать вам лучшее из обоих миров. Скорость rack_test
, когда вам не нужно проверять содержимое javascript и гибкость selenium
, когда вы это делаете.
Также этот код заботится о повторной заселенности семенных данных в случаях, когда это необходимо (этот метод предполагает, что вы используете seeds.rb для загрузки ваших данных семени - как и в текущем соглашении).
Добавьте следующий код в spec_helper.
config.use_transactional_fixtures = false
RSpec.configure do |config|
config.before(:suite) do
require "#{Rails.root}/db/seeds.rb"
end
config.before :each do
if Capybara.current_driver == :rack_test
DatabaseCleaner.strategy = :transaction
else
DatabaseCleaner.strategy = :truncation
end
DatabaseCleaner.start
end
config.after(:each) do
if Capybara.current_driver == :rack_test
DatabaseCleaner.clean
else
DatabaseCleaner.clean
load "#{Rails.root}/db/seeds.rb"
end
end
end
Спасибо Jo Liss за то, что указали путь.
PS: Как переключать драйверы на лету
В приведенном выше решении предполагается, что вы уже знаете, как переключаться с драйверами "на лету". В случае, если кто-то сюда сюда не делает, вот как:
Как указано выше, предположим, что вы обычно будете использовать драйвер capybara по умолчанию rack_test, но вам нужно использовать селен для тестирования некоторых материалов Ajaxy. Если вы хотите использовать драйвер selenium, используйте :js => true
или @javascript
для Rspec или огурца, соответственно. Например:
Пример Rspec:
describe "something Ajaxy", :js => true do
Пример огурца:
@javascript
Scenario: do something Ajaxy
Ответ 2
Использование транзакционных приборов будет быстрее, так как СУБД не фиксирует изменения (и, следовательно, не происходит тяжелая IO-перезагрузка базы данных между тестами), но, как вы знаете, не всегда будет работать.
У нас был некоторый успех с использованием баз данных SQLite в памяти в тестовой среде, поэтому тесты выполняются очень быстро, оставив транзакционные светильники выключенными. Эта опция также доступна для MySQL (используйте: опции для установки "ДВИГАТЕЛЬ = ПАМЯТЬ" ), но я никогда не делал этого лично, и если вы будете искать, вы найдете несколько потоков о связанных с ними предостережениях. Возможно, стоит посмотреть. В зависимости от вашей методологии тестирования может быть неприемлемо использовать другой механизм БД.
Я предлагаю вам включить транзакционные светильники и использовать DatabaseCleaner для выборочного отключения транзакционных светильников в группе примеров. Я не могу сказать, что я пробовал это, но поскольку у вас не было ответов, я понял, что что-то может помочь вам.
before(:all) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
before(:each) do
DatabaseCleaner.start
end
after(:each) do
DatabaseCleaner.clean
end
Если бы это был я, я бы включил это в помощника и назвал его как однострочный макрос из каждой примерной группы, для которой отключены транзакционные приборы.
Похоже, что действительно должен быть лучший способ, хотя.... удачи.
Ответ 3
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, :js => true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
Это из Avdi Grimm post об очистке базы данных и Rspec. Пошаговый анализ кода приведен в статье.
Ответ 4
Вы использовали Spork? Это значительно увеличивает скорость.