I have a lot of cookbooks and they are heavily tested with ChefSpec. I have more than 800 specs and it has become a problem to run them every time before committing code, because on my machine it takes about 20 minutes to run them. That makes ~0.(6)s per spec, which is not much, but adds up to long amount of time.
Is there any possibility to run ChefSpec/RSpec tests in parallel or somehow else increase speed?
Update 4 Jan 2014: The following idea is now implemented inside ChefSpec (>= 3.1.2). See Faster Specs part in Readme.
================================
This is a excerpt from an blogpost that covers this topic with some more details.
RSpec allows to extend modules with your own methods and the idea is to write method similar to let, but which will cache the results across examples too. Create a *spec_helper.rb* file somewhere in your Chef project and add the following lines there:
module SpecHelper
@@cache = {}
def shared( name, &block )
location = ancestors.first.metadata[:example_group][:location]
define_method( name ) do
@@cache[location + name.to_s] ||= instance_eval( &block )
end
end
def shared!( name, &block )
shared name, &block
before { __send__ name }
end
end
RSpec.configure do |config|
config.extend SpecHelper
end
Values from @@cache are never deleted, and you can use same names with this block, so I also use location of the usage, which looks like that: "./cookbooks/my_cookbook/spec/default_spec.rb:3". Now change let( :chef_run )
into shared( :chef_run )
in your specs:
describe "example::default" do
shared( :chef_run ) { ChefSpec::ChefRunner.new.converge described_recipe }
[...]
end
And when running the tests you will now have to include the spec_helper.rb too:
rspec --include ./relative/path/spec_helper.rb cookbooks/*/spec/*_spec.rb