Rspec, Cucumber: лучшая стратегия очистки базы данных - PullRequest
14 голосов
/ 21 марта 2011

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

  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 ?

P.S. Mysql, Rails 3, Rspec2, огурец

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

Ответы [ 4 ]

6 голосов
/ 20 июля 2012

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
5 голосов
/ 23 апреля 2011

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

Мы добились определенного успеха, используя базы данных 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

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

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

1 голос
/ 16 августа 2013
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.Пошаговый анализ кода есть в статье.

0 голосов
/ 21 марта 2011

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

...