Rspec, Cucumber: лучшая скорость очистки базы данных

Я хотел бы увеличить скорость моих тестов.

  1. Должен ли я использовать use_transactional_fixtures или пойти с database_cleaner драгоценный камень?
  2. Какая стратегия database_cleaner является лучшей? Я заметил, что после миграции из :truncation в :transaction мои более 800 примеров работают примерно в 4 раза быстрее!
  3. Должен ли я выключить use_transactional_fixtures когда я использую database_cleaner :transaction?
  4. Правда ли, что лучшая стратегия для rack_test это :transaction?
  5. Каковы лучшие практики для изменения стратегии на лету от :transaction в :truncation при использовании селена или akephalos?

PS Mysql, Rails 3, Rspec2, Огурец

PPS Я знаю о spork и parallel_test и их использовании. Но они оффтоп. Например, Spork экономит около 15-20 секунд на весь запуск пакета, но меняется с :transaction в :truncation резко увеличить время работы с 3,5 до 13,5 минут (разница 10 минут).

4 ответа

1., 2. & 4., Вы должны использовать транзакции (либо с use_transactional_fixtures или поддержка транзакций из самоцвета database_cleaner), если вы используете стандартный движок capybara, rack_test. Как вы заметили, использование транзакций значительно быстрее, чем использование стратегии усечения. Однако, когда запись в базу данных может проходить через разные потоки (как с селеном), транзакции не будут работать. Поэтому вам нужно использовать усечение (или заставить все проходить через один поток БД - другой вариант).

3. Да, вы должны выключить use_transactional_fixtures при использовании самоцвета database_cleaner, поскольку самоцвет поддерживает транзакции. Если вам нужны только транзакции, просто используйте use_transactional_fixtures и никогда не загружайте гем database_cleaner.

5. Следующий код будет переключаться между :transaction а также :truncation на лету. (Протестировано это с помощью rspec, capybara, rails3.)

Особенности Это должно дать вам лучшее из обоих миров. Скорость rack_test когда вам не нужно тестировать JavaScript и гибкость selenium когда вы делаете.

Также этот код заботится о повторном заполнении начальных данных в тех случаях, когда это необходимо (этот метод предполагает, что вы используете seed.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

Спасибо Джо Лисс за указание пути.

PS: как переключать драйверы на лету

Приведенное выше решение предполагает, что вы уже знаете, как переключать драйверы на лету. В случае, если некоторые, кто приезжает сюда, не делают, вот как:

Как и выше, давайте предположим, что вы обычно будете использовать драйвер по умолчанию для capybara rack_test, но вам нужно будет использовать селен для проверки некоторых вещей Ajaxy. Если вы хотите использовать драйвер селен, используйте :js => true или же @javascript для Rspec или огурца соответственно. Например:

Пример Rspec:

describe "something Ajaxy", :js => true do

Пример огурца:

@javascript
Scenario: do something Ajaxy

Использование фиксаций транзакций будет быстрее, поскольку СУБД не фиксирует изменения (и, следовательно, не происходит интенсивного ввода-вывода при перезагрузке базы данных между тестами), но, как вы знаете, не всегда будет работать.

Мы добились определенного успеха, используя базы данных SQLite в памяти в тестовой среде, поэтому тесты выполняются очень быстро, оставляя при этом транзакционные исправления отключенными. Эта опция также доступна для MySQL (используйте: опции, чтобы установить "ENGINE=MEMORY"), но я никогда не делал это лично, и если вы будете искать, вы найдете несколько тем о возможных предостережениях. Может стоит посмотреть. В зависимости от вашей методики тестирования может быть неприемлемо использовать другой механизм БД.

Я предлагаю вам включить транзакционные фикстуры и использовать гем DatabaseCleaner, чтобы выборочно отключать транзакционные фикстуры для каждой группы примеров. Не могу сказать, что пытался это сделать, но поскольку у вас не было ответов, я подумал, что что-то может вам помочь.

before(:all) do
  DatabaseCleaner.strategy = :transaction
  DatabaseCleaner.clean_with(:truncation)
end

before(:each) do
  DatabaseCleaner.start
end

after(:each) do
  DatabaseCleaner.clean
end

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

Похоже, что действительно должен быть лучший путь... удачи.

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

Это из поста Авди Гримм о очистителе базы данных и Rspec. Пошаговый анализ кода есть в статье.

Вы использовали Spork? Это значительно увеличивает скорость.

Другие вопросы по тегам