Chef’s Test Kitchen project allows for fast functional testing of infrastructure code. In the past few years, the rise of container technologies like Docker have allowed devops engineers to speed up this feedback cycle, since the startup time of a container is much faster than that of a VM image that needs to be cloned and then booted by a full hypervisor.
However, containers are not lightweight VMs, so there are some limitations when using them for testing infrastructure code. In particular, a container typically does not run a full init process, which makes it somewhat challenging to test low-level Chef resources like
service. Additionally, base container images provided by operating system vendors are extraordinarily minimal, often containing just a kernel, GNU coreutils and a package manager. It is wasteful to have to install a userland every test cycle just to simulate a real system.
There are two community-maintained Test Kitchen drivers, kitchen-dokken and kitchen-docker, that take different approaches to solving some of these problems. ChefDK ships with kitchen-dokken because it is the most closely coupled to Chef, but kitchen-docker has valuable use cases as well.
Kitchen-Dokken by Awesome Community Chef Sean O’Meara is optimized for speed and testing Chef recipes. It achieves this goal by using pre-built Docker images and using bind mounts to share data like the Chef Client itself and the cookbooks without the need to copy it into the container. This can result in significant speed improvements with no additional configuration burden. It blurs the lines between driver, provisioner, and transport and as such diverges from more “traditional” drivers. Currently it is specific to Chef use cases and is part of the ChefDK. It uses
systemd as the PID 1 inside the container to allow for testing of resources like
One challenge is that the bind mounts may make it difficult to use this driver in a Docker-in-Docker scenario e.g. in a Docker-based CI system like GitLab. It can be challenging to make sure the mounts across two Docker boundaries are configured properly.
Kitchen-docker, primarily maintained by Noah Kantrowitz, another Awesome Community Chef, is similar to other drivers in being relatively provisioner-agnostic. In other words, it is not Chef specific. When provisioning with Chef, the default behavior downloads and installs Chef Client just like other drivers. It provides the ability for more complex configuration (as well as allowing the use of alternate provisioners) but in general requires a slightly higher familiarity with Docker. Kitchen-docker uses minimal operating system distribution-provided containers from Docker Hub but these often require additional configuration to be useful, as mentioned above. Finally, kitchen-docker uses
sshd as the PID 1 inside the container and sends infrastructure code over the SSH connection, which makes for easier networking setup — no bind mounts are needed. However, this design means it is not possible to test resources like
service that expect to talk to an init system.
If you are a Chef user with simple testing needs, use kitchen-dokken.
If you are a Chef user with more complex testing needs or require features kitchen-dokken doesn’t support, try kitchen-docker. This is true particularly if you are trying to use it in conjunction with a Docker-based CI system.
If you are an Ansible/Puppet/not-Chef user, use kitchen-docker.
Both drivers are are fast due to the nature of low container overhead, though kitchen-dokken may often appear faster because more of the configuration is pre-baked.