Rspec,Cucumber:最佳速度数据库清洁策略

我想提高测试的速度。

  1. 我应该使用use_transactional_fixtures还是使用database_cleaner gem?
  2. 哪种database_cleaner策略最好? 我注意到从迁移后:truncation:transaction我的800多个例子运行速度快了4倍!
  3. 当我使用database_cleaner :transaction时,我应该关闭use_transactional_fixtures吗?
  4. Rack_test的最佳策略是:transaction吗?
  5. 在使用selenium或akephalos时,从:transaction:truncation的最佳实践是什么?

PS Mysql,Rails 3,Rspec2,Cucumber

PPS我知道spork和parallel_test并使用它们。 但他们是偏离主义的。 例如,Spork在整个套件运行中节省大约15-20秒,但从:transaction更改为:truncation显着地将运行时间从3.5增加到13.5分钟(差异10分钟)。

1.,2。&4.如果您使用的是capybara的默认引擎rack_test 您应该使用事务(使用use_transactional_fixtures或来自database_cleaner gem的事务支持)。 如您所述,使用事务比使用截断策略要快得多。 但是,当数据库写入可以通过不同的线程(与selenium一样)时,事务将不起作用。 因此,您需要使用截断(或强制所有内容通过一个数据库线程 – 另一个选项)。

3.是的,你应该在使用database_cleaner gem时关闭use_transactional_fixtures ,因为gem本身支持事务。 如果您只需要事务,那么只需使用use_transaction_fixtures并且永远不会加载database_cleaner gem。

5.以下代码将在:transaction:truncation之间切换。 (用rspec,capybara,rails3测试过。)

特点这应该给你两全其美。 当你不需要测试javascript的东西和selenium灵活性时, rack_test速度

此代码还负责在需要的情况下重新填充种子数据(此方法假定您使用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,但需要使用selenium来测试一些Ajaxy的东西。 当你想使用selenium驱动程序时,分别使用:js => true@javascript用于@javascript或黄瓜。 例如:

Rspec示例:

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

黄瓜的例子:

 @javascript Scenario: do something Ajaxy 

使用事务性夹具会更快,因为DBMS不提交更改(因此在测试之间没有重置IO重置数据库),但是您知道并不总是有效。

我们在测试环境中使用SQLite内存数据库取得了一些成功,因此测试运行得非常快,同时关闭了事务夹具。 这个选项也适用于MySQL(使用:选项来设置“ENGINE = MEMORY”),但我从来没有亲自完成它,如果你搜索,你会发现一些涉及警告的线索。 也许值得一瞧。 根据您的测试方法,使用不同的数据库引擎可能是不可接受的。

我建议你启用事务夹具并使用DatabaseCleaner gem来有选择地禁用每个示例组的事务夹具。 我不能说我已经尝试过这个但是因为你没有任何答案,我认为任何可能有助于你的事情。

 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 

这是来自Avdi Grimm关于数据库清理和Rspec的post 。 文章中逐步分析了代码。

你用过Spork吗? 它大大提高了速度。