Chef Chefspec

ChefSpec is a unit testing framework for testing Chef cookbooks. ChefSpec makes it easy to write examples and get fast feedback on cookbook changes without the need for virtual machines or cloud servers.ChefSpec runs our cookbooks locally with Chef Solo without actually converging a node.

Structure of Cookbooks for ChefSpec

When writing unit tests for our cookbook, the standard is to create a separate spec test for each recipe in the /spec folder.

# tree


├── chefignore

├── httpd_deploy

│   ├── Berksfile

│   ├── chefignore

│   ├── metadata.rb

│   ├──

│   ├── recipes         #Recipes

│   │   └── default.rb

│   ├── spec           

│   │   ├── spec_helper.rb

│   │   └── unit

│   │       └── recipes

│   │           └── default_spec.rb

│   └── test          

│       └── smoke

│           └── default

│               └── default_test.rb

└── starter

    ├── attributes

    │   └── default.rb

    ├── files

    │   └── default

    │       └── sample.txt

    ├── metadata.rb

    ├── recipes

    │   └── default.rb

    └── templates

        └── default

            └── sample.erb

Writing ChefSpec Program

# recipe/default.rb

package 'foo'

# spec/unit/recipes/default_spec.rb

require 'chefspec'

describe 'example::default' do

  let(:chef_run) { 'ubuntu', version: '16.04').converge(described_recipe) }

  it 'installs foo' do

    expect(chef_run).to install_package('foo')



ChefSpec Program

require 'chefspec'

At the top of the spec file, we require the chefspec gem. This is required so that our custom matchers are loaded. In larger projects, it is common practice to create a file named "spec_helper.rb" and include ChefSpec and perform other setup tasks in that file.

describe 'example::default' do

The describe keyword is part of RSpec and indicates that everything nested beneath is describing the example::default recipe. The convention is to have a separate spec for each recipe in your cookbook.

let(:chef_run) { 'ubuntu', version: '16.04').converge(described_recipe) }

The let block creates the ChefSpec:SoloRunner with mocked Ohai data for Ubuntu 16.04 from Fauxhai. It then does a fake Chef run with the run_list of example::default. Any subsequent examples can then refer to chef_run to make assertions about the resources that were created during the mock converge.


The SoloRunner allows us to simulate testing against the different operating systems (platforms) and versions by passing a parameter. It simulates the Chef run-in memory.


The described_recipe macro is a ChefSpec helper method that infers the recipe from the describe block. Alternatively, you could specify the recipe directly.

expect(chef_run).to install_package('foo')

Each of these examples defined expectations that desired packages will be installed.

expect(chef_run).to_not install_package('unzip')

Each of these examples defined expectations that desired packages not will be installed.

Relevant Blogs:

chef roles 

Chef files 

Google Cloud Platform 

Rundeck - Installation, and configuration

Recent Comments

No comments

Leave a Comment