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 Windows Server virtual machine. |
 | In this step, Test Kitchen applies your cookbook to the virtual environment. |
 | In this step, you connect to your virtual environment, typically over Remote Desktop or WinRM. |
 | 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 Windows Server virtual machine. Then you'll verify that everything's working. Finally, you'll destroy the instance.
1. Get the learn_chef_iis cookbook from GitHub
In the Learn the Chef basics and Manage a node with Chef server modules, you wrote a cookbook named learn_chef_iis that configures IIS web server. You'll run that cookbook on your test instance.
If you still have the learn_chef_iis 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_iis cookbook from GitHub.
Terminal: ~/learn-chef/cookbooks
$ | git clone https://github.com/learn-chef/learn_chef_iis.gitCloning into 'learn_chef_iis'...
|
Now cd there.
Terminal: ~/learn-chef/cookbooks
$ | cd ~/learn-chef/cookbooks/learn_chef_iis
|
The contents of ~/learn-chef/cookbooks/learn_chef_iis 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. Examine 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 your .kitchen.yml file looks like.
Editor: ~/learn-chef/cookbooks/learn_chef_iis/.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: vagrant
boot_timeout: 1200
gui: false
provisioner:
name: chef_zero
verifier:
name: inspec
transport:
name: winrm
elevated: true
username: Administrator
password: Pass@word1
platforms:
- name: windows-2012R2
driver:
customize:
memory: 2048
suites:
- name: default
run_list:
- recipe[learn_chef_iis::default]
verifier:
inspec_tests:
- test/smoke/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. |
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 Windows Server, the platforms sections contains only windows-2012r2. (This is the name you provided for your box in the previous part.)
Here's how the .kitchen.yml file breaks down.
- driver specifies the software that manages the machine. We're using the Vagrant Test Kitchen driver (list of other popular drivers). The Vagrant driver works with VirtualBox by default.
- 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 – Windows Server 2012 R2.
- 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_iis 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_iis directory, run kitchen list to see what's in the kitchen.
Terminal: ~/learn-chef/cookbooks/learn_chef_iis
$ | kitchen listInstance Driver Provisioner Verifier Transport Last Action Last Errordefault-windows-2012r2 Vagrant ChefZero Inspec Winrm <Not Created> <None>
|
Our kitchen includes just one instance – a Windows Server 2012 R2 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_iis
$ | kitchen create-----> Starting Kitchen (v1.20.0)-----> Creating <default-windows-2012r2>... Bringing machine 'default' up with 'virtualbox' provider... ==> default: Box 'chef/windows-server-2012r2-standard' could not be found. Attempting to find and install... default: Box Provider: virtualbox default: Box Version: >= 0 ==> default: Loading metadata for box 'chef/windows-server-2012r2-standard' default: URL: https://vagrantcloud.com/chef/windows-server-2012r2-standard ==> default: Adding box 'chef/windows-server-2012r2-standard' (v2.2.0) for provider: virtualbox default: Downloading: https://vagrantcloud.com/chef/boxes/windows-server-2012r2-standard/versions/2.2.0/providers/virtualbox.box ==> default: Importing base box 'chef/windows-server-2012r2-standard'... ==> default: Checking if box 'chef/windows-server-2012r2-standard' is up to date... ==> default: Setting the name of the VM: default-windows-2012r2_default_1524865412951_64787 ==> default: Clearing any previously set network interfaces... ==> default: Preparing network interfaces based on configuration... default: Adapter 1: nat ==> default: Forwarding ports... default: 3389 (guest) => 3389 (host) (adapter 1) default: 5985 (guest) => 5985 (host) (adapter 1) default: 5986 (guest) => 55986 (host) (adapter 1) default: 22 (guest) => 2222 (host) (adapter 1) ==> default: Running 'pre-boot' VM customizations... ==> default: Booting VM... ==> default: Waiting for machine to boot. This may take a few minutes... default: WinRM address: 127.0.0.1:5985 default: WinRM username: vagrant default: WinRM execution_time_limit: PT2H default: WinRM transport: negotiate ==> default: Machine booted and ready! ==> default: Checking for guest additions in VM... default: The guest additions on this VM do not match the installed version of default: VirtualBox! In most cases this is fine, but in rare cases it can default: prevent things such as shared folders from working properly. If you see default: shared folder errors, please make sure the guest additions within the default: virtual machine match the version of VirtualBox you have installed on default: your host and reload your VM. default: default: Guest Additions Version: 5.1.30 default: VirtualBox Version: 5.2 ==> default: Machine not provisioned because `--no-provision` is specified. [WinRM] Established Vagrant instance <default-windows-2012r2> created. Finished creating <default-windows-2012r2> (99m8.98s).-----> Kitchen is finished. (99m10.71s)
|
| 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. |
| If you receive a VERR_PATH_NOT_FOUND error, this might indicate that path name of your VirtualBox VM exceeds the maximum path length of your filesystem. In that case, move your learn-chef directory to a location higher in your directory structure (for example, C: on Windows) and run kitchen create a second time. |
Now run kitchen list again.
Terminal: ~/learn-chef/cookbooks/learn_chef_iis
$ | kitchen listInstance Driver Provisioner Verifier Transport Last Action Last Errordefault-windows-2012r2 Vagrant ChefZero Inspec Winrm Created <None>
|
The Last Action column now shows that the virtual machine has been created.
4. Apply the learn_chef_iis cookbook to your Test Kitchen instance
Now run kitchen converge to apply the cookbook to the Windows Server virtual machine.

Terminal: ~/learn-chef/cookbooks/learn_chef_iis
$ | kitchen converge-----> Starting Kitchen (v1.20.0)-----> Converging <default-windows-2012r2>... 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 package from https://packages.chef.io/files/stable/chef/14.0.202/windows/2016/chef-client-14.0.202-1-x64.msi Download complete. Successfully verified C:\Users\vagrant\AppData\Local\Temp\chef-client-14.0.202-1-x64.msi Installing Chef Omnibus package C:\Users\vagrant\AppData\Local\Temp\chef-client-14.0.202-1-x64.msi Installation complete Transferring files to <default-windows-2012r2> Starting Chef Client, version 14.0.202 Creating a new client identity for default-windows-2012r2 using the validator key. resolving cookbooks for run list: ["learn_chef_iis::default"] Synchronizing Cookbooks: - learn_chef_iis (0.1.0) Installing Cookbook Gems: Compiling Cookbooks... Converging 3 resources Recipe: learn_chef_iis::default * powershell_script[Install IIS] action run - execute "C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass -InputFormat None -File "C:/Users/vagrant/AppData/Local/Temp/chef-script20180427-864-1cbrjfr.ps1" * windows_service[w3svc] action enable * windows_service[w3svc] action start * template[c:\inetpub\wwwroot\Default.htm] action create - create new file c:\inetpub\wwwroot\Default.htm - update content in file c:\inetpub\wwwroot\Default.htm from none to a7298b --- c:\inetpub\wwwroot\Default.htm 2018-04-27 14:48:37.399942100 -0700 +++ c:\inetpub\wwwroot/chef-Default20180427-864-zvprav.htm 2018-04-27 14:48:37.399942100 -0700 @@ -1 +1,6 @@ +<html> + <body> + <h1>hello world</h1> + </body> +</html> Running handlers: Running handlers complete Chef Client finished, 2/4 resources updated in 36 seconds Downloading files from <default-windows-2012r2> Finished converging <default-windows-2012r2> (4m11.16s).-----> Kitchen is finished. (4m13.15s)
|
| 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_iis
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_iis
$ | kitchen listInstance Driver Provisioner Verifier Transport Last Action Last Errordefault-windows-2012r2 Vagrant ChefZero Inspec Winrm 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_iis
$ | kitchen converge-----> Starting Kitchen (v1.20.0)-----> Converging <default-windows-2012r2>... 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-windows-2012r2> Starting Chef Client, version 14.0.202 resolving cookbooks for run list: ["learn_chef_iis::default"] Synchronizing Cookbooks: - learn_chef_iis (0.1.0) Installing Cookbook Gems: Compiling Cookbooks... Converging 3 resources Recipe: learn_chef_iis::default * powershell_script[Install IIS] action run * windows_service[w3svc] action enable * windows_service[w3svc] action start * template[c:\inetpub\wwwroot\Default.htm] action create (up to date) Running handlers: Running handlers complete Chef Client finished, 0/4 resources updated in 04 seconds Downloading files from <default-windows-2012r2> Finished converging <default-windows-2012r2> (0m31.79s).-----> Kitchen is finished. (0m34.23s)
|
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_iis cookbook configures IIS and sets the home page to display "hello world". An easy way to verify this is to log into your test instance and run Invoke-WebRequest localhost.
The kitchen login command is the most common way to access your test instance. This command creates a WinRM connection into your instance and enables you to explore your test instance and verify its configuration.
Because you only want to run Invoke-WebRequest 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_iis
$ | kitchen exec -c '(Invoke-WebRequest -UseBasicParsing localhost).Content'-----> Execute command on default-windows-2012r2. <html> <body> <h1>hello world</h1> </body> </html>
|
You see that the web page contains "hello world" as expected.
| When you use the Vagrant driver, you can also assign a static IP address to your instance. This enables you to verify the configuration externally, such as from your workstation's web browser. You'll do so in the next module. |
Connecting to your Windows Server instance over Remote Desktop
Here, you ran kitchen exec to verify your configuration over WinRM. Although not required, you can also connect over Remote Desktop. Remote Desktop gives you full access to your Windows Server instance through its graphical interface. The way you connect to your instance depends on which driver you're using.
When you use the Vagrant driver, a VirtualBox window appears when you create the instance. Login through that window as either Administrator or vagrant – the password for both accounts is vagrant.
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_iis
$ | kitchen destroy-----> Starting Kitchen (v1.20.0)-----> Destroying <default-windows-2012r2>... ==> default: Forcing shutdown of VM... ==> default: Destroying VM and associated drives... Vagrant instance <default-windows-2012r2> destroyed. Finished destroying <default-windows-2012r2> (0m4.45s).-----> Kitchen is finished. (0m6.19s)
|
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_iis
$ | kitchen listInstance Driver Provisioner Verifier Transport Last Action Last Errordefault-windows-2012r2 Vagrant ChefZero Inspec Winrm <Not Created> <None>
|