Trying to understand this code

I have been given a cookbook and told to write tests for it. I am fairly new to chef and new to chef testing. I have done some testing before for Node.js but that’s it. The code block below is the one I am having trouble writing a test for. If I understand it right it is taking the usr/local… and replacing it’s contents with the source listed on the second line. Then reloads the Nginx service shortly after a delay. How do you write tests for that?

template ‘usr/local/nginx/conf/modsecurity.conf’ do
source ‘modsecurity.conf.erb’
notifies :reload, “service[nginx]”, :delayed
end

Hello,

Testing Chef resources is achieved with ChefSpec. You may find it helpful to run through the Learn Chef module for unit testing.

Learn Chef:

https://learn.chef.io/modules/unit-test-with-chefspec

ChefSpec:

https://github.com/chefspec/chefspec

https://github.com/chefspec/chefspec/tree/master/examples/template

I think you’ll likely have more questions, but this should get you started.

Brandon

Thanks, I have gone through the learn.chef.io but still am not 100% on it. Been looking at the docs but they only seem to show how to write the cookbooks or write certain types of tests. I can’t find any that are specific to the template styling. That’s why I came here to ask.

Hi @jkwysdom, welcome to the community!

The examples directory in the chefspec repo is a wealth of info for chefspec tests, which are considered a type of ‘unit’ test in Chef, with the unit being an individual resource.

For the template resource you pasted:

template ‘/usr/local/nginx/conf/modsecurity.conf’ do
    source ‘modsecurity.conf.erb’
    notifies :reload, “service[nginx]”, :delayed
end

You are telling chef-client to render the modsecurity.conf file at that path, using the template source modsecurity.conf.erb and to send a delayed (executed at the end of the chef-client run) notification to the chef service resource named ‘nginx’ telling it to run the :reload action.

You would need a chefspec statement like:

it 'some description of resource under test here' do
  expect(chef_run).to create_template('/usr/local/nginx/conf/modsecurity.conf').with(
    source 'modsecurity.conf.erb'
   )
  expect(chef_run).to notify('service[nginx]').to(:reload).delayed
end

There’s some more boilerplate to making this work, like ensuring chef_run is an instance of ChefSpec::SoloRunner or ChefSpec::ServerRunner but you can find these examples in the repo.

I’d also encourage you to look at test-kitchen and inspec testing, which is how integration testing is performed for chef cookbooks. Test-kitchen creates temporary machines and converges your recipe, inspec verifies the resutls.

An inspec test for this resource could look like:

describe file('/usr/local/nginx/conf/modsecurity.conf') do
  it { should exist }
  its('mode') { should cmp '0644' }
end

You can test other properties as well, this is documented with examples on the inspec file resource page

Hope that is clear.

Thanks, the inspec test is the one that helped. I am using inspec to write the tests so far. Noted the chefspec one down too for future use.