我想提高测试速度。
use_transactional_fixtures
还是使用database_cleaner
gem?:truncation
迁移到:transaction
后,我的800多个示例的运行速度提高了大约4倍!use_transactional_fixtures
时,我应该关闭:transaction
吗?:transaction
?:transaction
到:truncation
动态更改策略的最佳做法是什么?P.S。 Mysql,Rails 3,Rspec2,Cucumber
P.P.S。我了解spork和parallel_test并使用它们。但他们是偏离主义的。例如,Spork在整个套件运行中节省大约15-20秒,但从:transaction
更改为:truncation
会大大增加运行时间3.5到13.5分钟(差异10分钟)。
答案 0 :(得分:6)
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内容和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
感谢Jo Liss指明方向。
PS:如何动态切换驱动程序
上述解决方案假设您已经知道如何动态切换驱动程序。如果有人来这里不这样做,请按照以下方式进行:
如上所述,我们假设您通常会使用默认的capybara驱动程序rack_test,但需要使用selenium来测试一些Ajaxy的东西。当您想使用selenium驱动程序时,分别使用:js => true
或@javascript
代替Rspec或黄瓜。例如:
Rspec示例:
describe "something Ajaxy", :js => true do
黄瓜的例子:
@javascript
Scenario: do something Ajaxy
答案 1 :(得分: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
如果是我,我会把它当作一个帮助器,并将其称为每个示例组中的一行宏,需要关闭事务处理器。
似乎确实应该有一个更好的方法,但是......祝你好运。
答案 2 :(得分:1)
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的Avdi Grimm's post。文章中逐步分析了代码。
答案 3 :(得分:-1)
你用过Spork吗?它大大提高了速度。