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

pet*_*hka 14 database performance rspec ruby-on-rails 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,Cucumber

PPS我知道sporkparallel_test并使用它们.但他们是偏离主义的.例如,叉勺节省整个套件运行约15-20秒,而从改变:transaction:truncation显着增加从3.5到13.5分钟(10分钟差)运行时间.

sno*_*guy 6

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

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

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

特点这应该给你两全其美.当你不需要测试javascript的东西时的速度rack_test你做的时候的灵活性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
Run Code Online (Sandbox Code Playgroud)

谢谢Jo Liss指出方向.

PS:如何动态切换驱动程序

上述解决方案假设您已经知道如何动态切换驱动程序.如果有人来这里不这样做,请按以下方式:

如上所述,我们假设您通常会使用默认的capybara驱动程序rack_test,但需要使用selenium来测试一些Ajaxy的东西.当你想使用selenium驱动器分别使用:js => true@javascript用于Rspec或黄瓜时.例如:

Rspec示例:

describe "something Ajaxy", :js => true do
Run Code Online (Sandbox Code Playgroud)

黄瓜的例子:

@javascript
Scenario: do something Ajaxy
Run Code Online (Sandbox Code Playgroud)


MDa*_*ubs 5

使用事务性夹具会更快,因为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
Run Code Online (Sandbox Code Playgroud)

如果是我,我会把它当作一个帮助器,并将其称为每个示例组的单行宏,需要关闭事务夹具.

似乎真的应该有更好的方式,但是......祝你好运.


Spy*_*ros -1

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

  • 是的,我用勺子。但已经脱离主题了。Spork 保存 ~15 秒。开始时。但改变策略可以节省10分钟。对于我的测试套件... (2认同)