如何更快地在RoR上运行测试?

我正在使用Ruby on Rails 3并编写测试,但速度太慢了。 是否有一些好的配置或工具可以加快速度?

正如@eml所说,如果你使用RSpec,你可以使用Spork。 这基本上会激发环境(这是缓慢的部分)然后保持它,每次运行您的规格时都会分叉。

对于“环境始终加载”问题的更一般的解决方案,可以安装rails-sh并在shell中运行测试。

旁注:随着需求时间的优化,Ruby 1.9.3应该稍微缓解这个问题。

除非您需要,否则最大的速度增益可能来自于小心不要访问数据库。 模拟对象而不是从数据库中获取对象,和/或(例如,如果您使用的是工厂女孩)尽可能使用Factory.build(:stuff)而不是Factory(:stuff)。 只有当你这样做时,你应该开始尝试用spork进一步优化

更新:就个人而言,我也开始认为你不应该对你的测试速度感到不知所措。 更快更好,但随着应用程序的增长,测试套件将会增长,但无论多么小心,它最终会变得比你想要的慢。 我越来越依赖自动测试gem测试更改代码并在后台工作(guard-rspec做类似的工作)。 当您的应用程序达到1000个测试时,您不希望每次进行更改时都等待整个套件完成,无论测试运行得多么快。

恕我直言,测试的主要减缓部分是灯具的默认配置。 如果您的配置是(在test/test_helper.rb ):

 class ActiveSupport::TestCase self.use_transactional_fixtures = false self.pre_loaded_fixtures = false self.use_instantiated_fixtures = true 

然后在每个测试方法之前,从旧数据中清除测试数据库,填充所有表,将所有记录读入内存。

如果您将设置更改为相反的设置:

 class ActiveSupport::TestCase self.use_transactional_fixtures = true self.pre_loaded_fixtures = true self.use_instantiated_fixtures = false 

然后,每个测试文件只重建一次数据库,并且只加载每个测试方法中真正需要的记录。

它取决于测试数据集的大小,是否可以找到可接受的测试数据库创建时间。 当我有一些非常大的测试数据时,我只在整个测试套件之前加载了一次灯具,但是那个项目是在Rails 1中,我已经对其进行了大量修改,所以我不知道怎么做在Rails 3中(至少在某个新项目中问题开始变得痛苦之前)。

关于测试是否应该访问数据库存在无休止的讨论。 如果您认为他们应该(因为数据库合作也应该进行测试),那么您可以检查设置这些参数是否有助于您(或任何人阅读这些答案)。

我推荐SporkGuard ,它们都能与RSpec完美配合。

Spork可以帮助您更快地运行测试, http: Spork

Guard可以帮助您自动运行测试。 http://railscasts.com/episodes/264-guard

尝试开发,以便无需加载整个Rails应用程序框架即可执行大多数测试。 在你的规范助手中,如果只执行快速测试,请跳过加载环境或rpec / rails,例如…

 # /spec/spec_helper.rb if RSpec.configuration.inclusion_filter[:fast] # Setup required for fast tests in particular (if any) # ... else ENV["RAILS_ENV"] ||= 'test' require File.expand_path("../../config/environment", __FILE__) require 'rspec/rails' Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} end RSpec.configure do |config| # ... unless RSpec.configuration.inclusion_filter[:fast] # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false # instead of true. config.use_transactional_fixtures = true end end 

要将测试标记为“快速”,请在其调用或周围的describe调用中添加, :fast => true选项。

要仅运行快速测试,请从命令shell rspec --tag fast执行rspec --tag fast

很难弄清楚如何构造代码,以便测试可以与Rails分开运行(当然,您仍然希望进行不单独运行的function和集成测试)。

我的库中的一个技巧是避免直接在ActiveRecord模型或其他类似的代码上编写代码,而是更喜欢在mixin模块上编写代码。 您可以通过将Subject定义为由该模块扩展的对象来测试mixin模块…

 describe 'MyModule', :fast => true subject{ Object.new.tap{|o| o.extend MyModule} } it 'does something' do # ... end end