Question

How can I write a unit test for a Chef provider?

So far, our unit testing strategy uses ChefSpec for recipes, and we stuff most of the interesting logic for our providers in libraries to make the logic more testable. However, we still run into issues where our providers are calling other resources (among other simple logic issues). For example:

action :run do

   helper = Helper.new
   template '/etc/hosts' do
     source 'hosts.erb'
     variables ({
              "host" => @new_resource.host,
              "ip_address" => node['ipaddress']
          })
     only_if { helper.update_hosts }
   end

   service 'httpd' do
      action :restart
   end
end

(this is not real code, just a trivial example)

What we'd like to do is test this provider in isolation to check for logic errors. ChefSpec has the capability of stepping into an LWRP, but it looks like that would force us to put the LWRP into a recipe, and many of our cookbooks are basically LWRP libraries with no recipes. We'd also just like to keep a clean separation in our tests, so it's obvious what component failed by looking at the file name.

Additionally, it would be nice if the test would automatically fail if there are any syntax errors in the LWRP definition. For example:

action :run do
   template '/etc/hosts/' do
     source_whoops 'hosts.erb'
     action :whoops
   end
end

It would be really nice if the above statement would cause the test to fail due to the attribute name being defined incorrectly, and the action name not existing (just like ChefSpec).

The only solution I've come up with is to basically create a "test cookbook" - a separate cookbook that defines each LWRP 1:1 with a single recipe, so ChefSpec can step into it that way. It seems like a reasonable, but less than ideal solution.

Was it helpful?

Solution

Looks like there is a (very recent) solution to this.

First, this pull request would basically do what I'm asking, although it has been rejected by the ChefSpec maintainer for understandable reasons.

The maintainer suggests to use a mycookbook_test pattern - a separate cookbook keeps all the unit tests. This would allow a simple 1 recipe-per-lwrp approach.

Additionally, this approach keeps the cookbook clear of any unit tests, which is nice for consumers of the cookbook. Consumers may want to run their own unit tests, and there's no need (or desire) to run tests on third party cookbooks.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top