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 AWS, 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
| ---
driver:
name: ec2
aws_ssh_key_id: learn-chef
region: us-east-1
availability_zone: b
subnet_id: subnet-3f22bd15
instance_type: t2.micro
image_id: ami-b81dbfc5
security_group_ids: ["sg-0e08cf75"]
retryable_tries: 120
provisioner:
name: chef_zero
verifier:
name: inspec
transport:
ssh_key: /root/.ssh/learn-chef.pem
platforms:
- name: centos-7
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. |
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 AWS Test Kitchen driver (list of other popular drivers).
- 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.
- 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 Ec2 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>... Detected platform: centos version 7 on x86_64. Instance Type: t2.micro. Default username: centos (default). If you are not using an account that qualifies under the AWSfree-tier, you may be charged to run these suites. The chargeshould be minimal, but neither Test Kitchen nor its maintainersare responsible for your incurred costs. Instance <i-0b57e9fbb171aba6e> requested. Polling AWS for existence, attempt 0... Attempting to tag the instance, 0 retries EC2 instance <i-0b57e9fbb171aba6e> created. Waited 0/600s for instance <i-0b57e9fbb171aba6e> volumes to be ready. Waited 5/600s for instance <i-0b57e9fbb171aba6e> volumes to be ready. Waited 10/600s for instance <i-0b57e9fbb171aba6e> volumes to be ready. Waited 0/600s for instance <i-0b57e9fbb171aba6e> to become ready. Waited 5/600s for instance <i-0b57e9fbb171aba6e> to become ready. Waited 10/600s for instance <i-0b57e9fbb171aba6e> to become ready. Waited 15/600s for instance <i-0b57e9fbb171aba6e> to become ready. EC2 instance <i-0b57e9fbb171aba6e> ready (hostname: ec2-35-170-246-152.compute-1.amazonaws.com). Waiting for SSH service on ec2-35-170-246-152.compute-1.amazonaws.com:22, retrying in 3 seconds [SSH] Established Finished creating <default-centos-7> (0m41.79s).-----> Kitchen is finished. (0m45.38s)
|
| 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 Ec2 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 curl... 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.1144/metadata.txt trying curl... 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.1144/chef-14.0.202-1.el7.x86_64.rpm trying curl... 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.1144/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:09:32.565917796 +0000 +++ /var/www/html/.chef-index20180427-1273-1cyc0nm.html 2018-04-27 19:09:32.564917743 +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 14 seconds Downloading files from <default-centos-7> Finished converging <default-centos-7> (0m46.08s).-----> Kitchen is finished. (0m49.57s)
|
| 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 Ec2 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 02 seconds Downloading files from <default-centos-7> Finished converging <default-centos-7> (0m8.42s).-----> Kitchen is finished. (0m12.56s)
|
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>... EC2 instance <i-0b57e9fbb171aba6e> destroyed. Finished destroying <default-centos-7> (0m0.69s).-----> Kitchen is finished. (0m4.90s)
|
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 Ec2 ChefZero Inspec Ssh <Not Created> <None>
|