Contributors30 minutes | Test Kitchen enables you to run your cookbooks in a temporary environment that resembles production. With Test Kitchen, you confirm that things are working before you deploy your code to a test, preproduction, or production environment. Many users incorporate this kind of local development as part of their overall Chef workflow. |
In this part, you'll run through the Test Kitchen workflow to get the hang of things. You'll apply the web server cookbook you wrote in the _Manage a node with Chef server_ module on a local test instance.

 | In this step, Test Kitchen creates an instance of your virtual environment, for example, a CentOS virtual machine. |
 | In this step, Test Kitchen applies your cookbook to the virtual environment. |
 | In this step, Test Kitchen creates an SSH session into your virtual environment. |
 | In this step, you manually verify that your virtual environment is configured as you expect. |
 | In this step, Test Kitchen shuts down and destroys your virtual environment. |
In this module, you perform the verify step manually. In practice, you typically write tests that automatically verify whether your configuration works as you expect. You'll learn about local testing in a future module.
Here, you'll get a copy of the web server cookbook that you created in the earlier modules. Then you'll apply that cookbook on a CentOS virtual machine. Then you'll verify that everything's working. Finally, you'll destroy the instance.
1. Get the learn_chef_httpd cookbook from GitHub
In the Learn the Chef basics and Manage a node with Chef server modules, you wrote a cookbook named learn_chef_httpd that configures Apache web server. You'll run that cookbook on your test instance.
If you still have the learn_chef_httpd cookbook on your system, you're all set up. Otherwise, follow these steps to get it.
Start by creating the ~/learn-chef/cookbooks directory if it does not already exist.
Terminal: ~
$ | mkdir ~/learn-chef/cookbooks
|
Now cd there.
Terminal: ~
$ | cd ~/learn-chef/cookbooks
|
Next, clone the learn_chef_httpd cookbook from GitHub.
Terminal: ~/learn-chef/cookbooks
$ | git clone https://github.com/learn-chef/learn_chef_httpd.gitCloning into 'learn_chef_httpd'...
|
Now cd there.
Terminal: ~/learn-chef/cookbooks
$ | cd ~/learn-chef/cookbooks/learn_chef_httpd
|
The contents of ~/learn-chef/cookbooks/learn_chef_httpd is the same as what you built in the Manage a node with Chef server module. You can examine this directory to familiarize yourself with its contents.
| Remember that Chef Supermarket is also a place for the community to share cookbooks. You'll learn more about community cookbooks in later modules. |
2. Create the Test Kitchen configuration file
When you use the chef generate cookbook command to create a cookbook, Chef creates a file named .kitchen.yml in the root directory of your cookbook. .kitchen.yml defines what's needed to run Test Kitchen, including which virtualization provider to use, how to run Chef, and what platforms to run your code on.
Here's what the initial .kitchen.yml file looks like.
Editor: ~/learn-chef/cookbooks/learn_chef_httpd/.kitchen.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| ---
driver:
name: vagrant
provisioner:
name: chef_zero
verifier:
name: inspec
platforms:
- name: centos-7
suites:
- name: default
run_list:
- recipe[learn_chef_httpd::default]
attributes: |
| On Linux and macOS, .kitchen.yml is a hidden file. Run ls -a if you want to see it from your terminal window. |
| In the latest releases of Test Kitchen, the .kitchen.yml file is named without the leading dot and will no longer be hidden. For example, kitchen.yml. However, the old format with the leading dot will remain backward compatible. |
We provide this configuration for the Vagrant and VirtualBox version of this module. To configure Test Kitchen to create CentOS instances on Azure, start by modifying .kitchen.yml like this.
Editor: ~/learn-chef/cookbooks/learn_chef_httpd/.kitchen.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| ---
driver:
name: azurerm
driver_config:
subscription_id: 12345678-YOUR-GUID-HERE-123456789ABC
location: East US
machine_size: Standard_D1
transport:
ssh_key: /root/.ssh/learn-chef.pem
provisioner:
name: chef_zero
verifier:
name: inspec
platforms:
- name: centos-7
driver_config:
image_urn: OpenLogic:CentOS:7.4:latest
vm_name: centos-vm
vm_tags:
ostype: linux
distro: centos
suites:
- name: default
run_list:
- recipe[learn_chef_httpd::default]
verifier:
inspec_tests:
- test/integration/default
attributes: |
| In the latest releases of Test Kitchen, you won't have to specify nearly as much of the preceding configuration. |
Next, replace these values:
subscription_id with your subscription ID. You can find yours on the first line of your ~/.azure/credentials file.location with the Azure region where you'll run your test instances.ssh_key with the full path to your SSH private key.
This example uses the Standard_D1VM size, which we recommend for this module. In practice, you would choose a VM size that fits your requirements.
Test Kitchen can manage more than one instance at a time to enable you to test your cookbooks on multiple platforms. The default configuration creates both an Ubuntu and a CentOS virtual machine. Since we want only CentOS, the platforms sections contains only centos-7.
Here's how the .kitchen.yml file breaks down.
- driver specifies the software that manages the machine. We're using the Azure Test Kitchen driver (list of other popular drivers).
- driver_config specifies additional configuration options for the Azure Test Kitchen driver, including your subscription ID, the region where you'll run your test instances, and the VM size.
- provisioner specifies how to run Chef. We use
chef_zero because it enables you to mimic a Chef server environment on your local machine. This allows us to work with node attributes and other Chef server features. - transport specifies how to execute commands remotely on the test instance. WinRM is the default transport on Windows; SSH is the default on all other operating systems. When working with cloud instances, this is where you specify your SSH key pair.
- verifier specifies which application to use when running automated tests. You'll learn more about automated testing in a future module.
- platforms specifies the target operating systems. We're targeting just one – CentOS 7.
- suites specifies what we want to apply to the virtual environment. You can have more than one suite. We define just one, named
default. This is where we provide the run-list, which defines which recipes to run and in the order to run them. Your run-list contains one recipe – the learn_chef_httpd cookbook's default recipe.
The Chef documentation explains the structure of the .kitchen.yml file in greater detail, and also explains more about the available settings.
3. Create the Test Kitchen instance
Now you'll provision a virtual machine to serve as your test environment. This is the kitchen create step in our workflow.

We often call the set of virtual environments that's created by Test Kitchen simply a kitchen.
From the ~/learn-chef/cookbooks/learn_chef_httpd directory, run kitchen list to see what's in the kitchen.
Terminal: ~/learn-chef/cookbooks/learn_chef_httpd
$ | kitchen listInstance Driver Provisioner Verifier Transport Last Action Last Errordefault-centos-7 Azurerm ChefZero Inspec Ssh <Not Created> <None>
|
Our kitchen includes just one instance – a CentOS 7 virtual machine that's configured to run the default suite. The Last Action column shows that the virtual machine is not yet created.
Create the instance now by running kitchen create.
Terminal: ~/learn-chef/cookbooks/learn_chef_httpd
$ | kitchen create-----> Starting Kitchen (v1.20.0)-----> Creating <default-centos-7>... Creating Resource Group: kitchen-default-centos-7-20180427T191237 Creating deployment: deploy-271a06434d9ed237 Adding public key from /root/.ssh/learn-chef.pem.pub to the deployment. Resource Microsoft.Network/virtualNetworks 'vnet' provisioning status is Running Resource Microsoft.Compute/virtualMachines 'centos-vm' provisioning status is Running Resource Microsoft.Compute/virtualMachines 'centos-vm' provisioning status is Running Resource Microsoft.Compute/virtualMachines 'centos-vm' provisioning status is Running Resource Microsoft.Compute/virtualMachines 'centos-vm' provisioning status is Running Resource Microsoft.Compute/virtualMachines 'centos-vm' provisioning status is Running Resource Microsoft.Compute/virtualMachines 'centos-vm' provisioning status is Running Resource Microsoft.Compute/virtualMachines 'centos-vm' provisioning status is Running Resource Microsoft.Compute/virtualMachines 'centos-vm' provisioning status is Running Resource Microsoft.Compute/virtualMachines 'centos-vm' provisioning status is Running Resource Microsoft.Compute/virtualMachines 'centos-vm' provisioning status is Running Resource Microsoft.Compute/virtualMachines 'centos-vm' provisioning status is Running Resource Microsoft.Compute/virtualMachines 'centos-vm' provisioning status is Running Resource Template deployment reached end state of 'Succeeded'. IP Address is: 52.224.53.95 [kitchen-271a06434d9ed237.eastus.cloudapp.azure.com] Finished creating <default-centos-7> (2m51.34s).-----> Kitchen is finished. (2m53.49s)
|
| If you need to destroy your instance before you complete this module, run kitchen destroy. You can later run kitchen create to pick back up where you left off on a fresh instance. |
Now run kitchen list again.
Terminal: ~/learn-chef/cookbooks/learn_chef_httpd
$ | kitchen listInstance Driver Provisioner Verifier Transport Last Action Last Errordefault-centos-7 Azurerm ChefZero Inspec Ssh Created <None>
|
The Last Action column now shows that the virtual machine has been created.
4. Apply the learn_chef_httpd cookbook to your Test Kitchen instance
Now run kitchen converge to apply the cookbook to the CentOS virtual machine.

Terminal: ~/learn-chef/cookbooks/learn_chef_httpd
$ | kitchen converge-----> Starting Kitchen (v1.20.0)-----> Converging <default-centos-7>... Preparing files for transfer Preparing dna.json Resolving cookbook dependencies with Berkshelf 6.3.1... Removing non-cookbook files before transfer Preparing validation.pem Preparing client.rb-----> Installing Chef Omnibus (install only if missing) Downloading https://omnitruck.chef.io/install.sh to file /tmp/install.sh Trying wget... Download complete. el 7 x86_64 Getting information for chef stable for el... downloading https://omnitruck.chef.io/stable/chef/metadata?v=&p=el&pv=7&m=x86_64 to file /tmp/install.sh.1562/metadata.txt trying wget... sha1 dedf02c8ac06a6e6927b5fef64c0ff50e4cba154 sha256 14ca797942b9a5b4e9c7b0abdb4dada1c2a2c783e5f264b422f36a8993439d78 url https://packages.chef.io/files/stable/chef/14.0.202/el/7/chef-14.0.202-1.el7.x86_64.rpm version 14.0.202 downloaded metadata file looks valid... downloading https://packages.chef.io/files/stable/chef/14.0.202/el/7/chef-14.0.202-1.el7.x86_64.rpm to file /tmp/install.sh.1562/chef-14.0.202-1.el7.x86_64.rpm trying wget... Comparing checksum with sha256sum... WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING You are installing an omnibus package without a version pin. If you are installing on production servers via an automated process this is DANGEROUS and you will be upgraded without warning on new releases, even to new major releases. Letting the version float is only appropriate in desktop, test, development or CI/CD environments. WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING Installing chef installing with rpm... warning: /tmp/install.sh.1562/chef-14.0.202-1.el7.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY Updating / installing... Thank you for installing Chef! Transferring files to <default-centos-7> Starting Chef Client, version 14.0.202 Creating a new client identity for default-centos-7 using the validator key. resolving cookbooks for run list: ["learn_chef_httpd::default"] Synchronizing Cookbooks: - learn_chef_httpd (0.1.0) Installing Cookbook Gems: Compiling Cookbooks... Converging 3 resources Recipe: learn_chef_httpd::default * yum_package[httpd] action install - install version 0:2.4.6-67.el7.centos.6.x86_64 of package httpd * service[httpd] action enable - enable service service[httpd] * service[httpd] action start - start service service[httpd] * template[/var/www/html/index.html] action create - create new file /var/www/html/index.html - update content in file /var/www/html/index.html from none to ef4ffd --- /var/www/html/index.html 2018-04-27 19:16:59.632357846 +0000 +++ /var/www/html/.chef-index20180427-1723-13ym7h5.html 2018-04-27 19:16:59.632357846 +0000 @@ -1 +1,6 @@ +<html> + <body> + <h1>hello world</h1> + </body> +</html> - restore selinux security context Running handlers: Running handlers complete Chef Client finished, 4/4 resources updated in 45 seconds Downloading files from <default-centos-7> Finished converging <default-centos-7> (1m24.16s).-----> Kitchen is finished. (1m27.02s)
|
| We use the term converge to describe the process of bringing a system closer to its desired state. When you see the word converge, think test and repair. |
| In practice, if you had more than one platform specified in your .kitchen.yml file, then you should specify the platform/instance you want to test your cookbook on when you run kitchen converge. For example, kitchen converge default-windows-2012r2. Otherwise, Test Kitchen would test your cookbook on all the platforms specified in your .kitchen.yml file. Incidentally, the platform specification is a concatenation of the suites name and the platform name in your .kitchen.yml. Therefore, default-windows-2012r2 is derived from this exerpt from your .kitchen.yml: |
Terminal: Example
| platforms: - name: windows-2012r2 suites: - name: default
|
Test Kitchen runs chef-client on the instance. When the chef-client run completes successfully, Test Kitchen exits with exit code 0. Run the following to check the exit code.
Terminal: ~/learn-chef/cookbooks/learn_chef_httpd
If you receive a result other than 0, fix the errors that were reported. Then run kitchen converge to apply the changes and again check the exit code.
Run kitchen list to see the latest status.
Terminal: ~/learn-chef/cookbooks/learn_chef_httpd
$ | kitchen listInstance Driver Provisioner Verifier Transport Last Action Last Errordefault-centos-7 Azurerm ChefZero Inspec Ssh Converged <None>
|
kitchen converge takes longer the first time you run it on a new instance because Test Kitchen needs to install the Chef tools. Run kitchen converge a second time to see how much faster it is.
Terminal: ~/learn-chef/cookbooks/learn_chef_httpd
$ | kitchen converge-----> Starting Kitchen (v1.20.0)-----> Converging <default-centos-7>... Preparing files for transfer Preparing dna.json Resolving cookbook dependencies with Berkshelf 6.3.1... Removing non-cookbook files before transfer Preparing validation.pem Preparing client.rb-----> Chef Omnibus installation detected (install only if missing) Transferring files to <default-centos-7> Starting Chef Client, version 14.0.202 resolving cookbooks for run list: ["learn_chef_httpd::default"] Synchronizing Cookbooks: - learn_chef_httpd (0.1.0) Installing Cookbook Gems: Compiling Cookbooks... Converging 3 resources Recipe: learn_chef_httpd::default * yum_package[httpd] action install (up to date) * service[httpd] action enable (up to date) * service[httpd] action start (up to date) * template[/var/www/html/index.html] action create (up to date) Running handlers: Running handlers complete Chef Client finished, 0/4 resources updated in 04 seconds Downloading files from <default-centos-7> Finished converging <default-centos-7> (0m11.86s).-----> Kitchen is finished. (0m14.36s)
|
This run was faster not only because the instance already had the Chef tools installed, but also because it was already in the desired state, so Chef had no work to do.
5. Verify that your Test Kitchen instance is configured as expected
The next step in the Test Kitchen workflow is to verify the configuration.

In practice, you typically write automated tests that verify whether your instance is configured as you expect. Having automated tests enables you to quickly verify that your configuration works as you add features to your cookbook. In fact, many Chef users take a test-driven approach, where you write your tests first before you write any Chef code.
You'll learn more about automated testing in a future module. For now, let's verify the configuration manually. Recall that the learn_chef_httpd cookbook configures Apache and sets the home page to display "hello world". An easy way to verify this is to log into your test instance and run curl localhost.
The kitchen login command is the most common way to access your test instance. This command creates an SSH connection into your instance and enables you to explore your test instance and verify its configuration.
Because you only want to run curl localhost, you can run kitchen exec to run a single command.
Run the following command to verify the contents of your web server's home page.
Terminal: ~/learn-chef/cookbooks/learn_chef_httpd
$ | kitchen exec -c 'curl localhost'-----> Execute command on default-centos-7. <html> <body> <h1>hello world</h1> </body> </html>
|
You see that the web page contains "hello world" as expected.
6. Delete the Test Kitchen instance
We're all done with our virtual machine, so now run the kitchen destroy command to delete it.

Terminal: ~/learn-chef/cookbooks/learn_chef_httpd
$ | kitchen destroy-----> Starting Kitchen (v1.20.0)-----> Destroying <default-centos-7>... Azure environment: Azure Destroying Resource Group: kitchen-default-centos-7-20180427T191237 Destroy operation accepted and will continue in the background. Finished destroying <default-centos-7> (0m1.66s).-----> Kitchen is finished. (0m3.96s)
|
Run kitchen list and you'll see that the Last Action column shows that the virtual machine no longer exists.
Terminal: ~/learn-chef/cookbooks/learn_chef_httpd
$ | kitchen listInstance Driver Provisioner Verifier Transport Last Action Last Errordefault-centos-7 Azurerm ChefZero Inspec Ssh <Not Created> <None>
|