Chefspec Basics - Initial notes
This post sums up the various aspects of writing Chefspec tests so that when I forget I can quick check here. Hopefully this will be of use to others. All examples refer to an example cookbook on Github.
Layout
Chefspec conforms to the rspec layout and requires your tests to end with “_spec.rb” (unless you override that) and placed under the “spec” directory. For example (not all files shown)
chefspec_example/
├── README.md
├── files
├── libraries
├── metadata.rb
├── providers
├── recipes
├── resources
├── spec
│ ├── recipes
│ │ └── default_spec.rb
│ └── spec_helper.rb
└── templates
Spechelper File
Since you need to require some common libraries for every test it makes sense to put these in a separate file that can easily be included in all tests
I’ve also activated the test coverage checker on the last line. It gives you a nice compliment if you get 100% test coverage :-)
Anatomy of a Test
First I’ll post a complete test then break it down
Line 1 - Require helper file
This is simply to get the appropriate libraries loaded
Line 4 - Create an “example group”
This is how you can group a set of related tests using describe
Line 10 Onwards - The tests
Then come the meat of the matter and the whole point of this exercise, namely, the test themselves. Taking the file test as an example :
The it keyword describes an example which is another way of saying “the thing I want to test”. In this case we are testing for the presence of a static file with the given owner of “example” and mode “0755”. The other tests (aka examples) test for common Chef attributes such as templates, packages and services.
Note that we can also test our own custom resources (in this case a LWRP called “chefspec_example”). This was done in a way very similar to the built in Chef resources
in the above snippet we are testing for the presence of the “chefspec_example” resource that has the “doit” attribute.
More on how to define custom matchers shortly.
Actually Executing the Tests
To run the tests simply go to the base of your cookbook and call rspec since Chefspec is an extension of rspec :
user@example.com chefspec_example $ rspec
This will run your tests and hopefully you’ll be basking in show you glorious green. You can get more information about passing tests (to watch the progress)
user@example.com chefspec_example $ rspec -f d
Testing your own LWRPs
You may have noticed that you can test that things happened, such as
- create_cookbook_file
- install_package
- enable_service
how might I test my own resource you ask? That is done with custom matchers. These are placed in the libraries directory of your cookbook with the special name matchers.rb. Thus chefspec_example/libraries/matchers.rb. The contents of which takes the form
The first thing to note is that all custom matcher libraries need to be wrapped in a check for Chefspec. Then we create a matcher method which will match the test we defined above using create_chefspec_example.
Other Observations
Fauxhai
There are lots of examples on the ‘net that show Fauxhai being explicitly loaded like this
however this does not seem necessary. All you need to do is create your Runner instance with the desired platform and version; Fauxhai will then automagically be invoked
Quoting of numbers
For permissions you need to be consistent when quoting numbers specified in resource attributes. Either quote both the test and recipe or neither; for example,
Notice that both examples are quoted. Having one quoted and the other not will lead to failed tests since it is technically a different resource.