Testing Docker containers with BATS

BATS (Bash Automated Testing System) allows you to have quick and easy tests in a very natural language, without the need of a lot of dependencies. BATS can also grow in complexity as per your requirement. In this section, we'll use Docker with Docker Compose to handle the build and a Makefile to tie the dependencies between the build process and the BATS testing process; this will make it easier to later integrate this process into a CI system.

Getting ready

To step through this recipe, you will need:

  • A working Docker installation
  • A BATS installation (it's available for all major Linux distributions and Mac OS)

Note

BATS Version 0.4.0 is used in this chapter.

How to do it…

Let's start with this simple Dockerfile that will install Apache and run it after clearing the cache:

FROM debian:stable-slim
LABEL name="apache"
LABEL maintainer="John Doe <[email protected]>"
LABEL version=1.0
RUN apt-get update -y 
    && apt-get install -y --no-install-recommends apache2=2.4.10-10+deb8u7 
    && apt-get clean 
    && rm -rf /var/lib/apt/lists/*
EXPOSE 80
ENTRYPOINT ["/usr/sbin/apache2ctl"]
CMD ["-D", "FOREGROUND"]

For convenience, let's create a docker-compose.yml file so the image can be built and run easily:

version: '2'

services:
  http:
    build: .
    image: demo-httpd
    ports:
      - "80:80"

This way, running docker-compose up will also build the image if absent. Alternatively, to just build the image, use this code:

$ docker-compose build

Creating BATS tests

We'll now test two of the main actions this image is supposed to do:

  • Install Apache 2.4.10
  • Clean the APT cache

Start by creating a test folder at the root of our repository that will host the BATS tests:

$ mkdir test

Our first test is to verify that the installed version of Apache is 2.4.10, as required. How would we do it manually? We'd probably just execute the following and check the output:

$ apache2ctl -v
Server version: Apache/2.4.10 (Debian)

This translates in Docker with our image in the following command (-v being the command (CMD) for the apache2ctl ENTRYPOINT instruction):

$ docker run --rm demo-httpd:latest -v
Server version: Apache/2.4.10 (Debian)

Basically, now we just have to run grep for the correct version:

$ docker run --rm demo-httpd:latest -v | grep 2.4.10
Server version: Apache/2.4.10 (Debian)

If grep is successful, it returns 0:

$ echo $?
0

A simple BATS test for a command return code looks like this:

@test "test title" {
  run <some command>
  [ $status -eq 0 ]
}

We now have everything we need to write our first BATS test in test/httpd.bats:

@test "Apache version is correct" {
  run docker run --rm demo-httpd:latest -v | grep 2.4.10
  [ $status -eq 0 ]
}

To execute our test, let's launch BATS with the folder containing the tests as arguments:

$ bats test
 
Ÿ
 Apache version is correct

1 test, 0 failures  

Good! We're now assured that the correct Apache version is installed.

Let's ensure the APT cache is cleaned after we build the image so we don't waste precious space. Deleting the APT lists means the /var/lib/apt/lists folder will become empty, so if you count the files in this folder after this, it should return 0:

$ ls -1 /var/lib/apt/lists | wc -l

However, we cannot just send this command to the container like we did for the Apache version; the entry point is apache2ctl, and it needs to be overridden by sh on the docker run command line. Here's the apt.bats test file, executing the shell command instead of apache2ctl, expecting a successful execution and an output of 0:

@test "apt lists are empty" {
  run docker run --rm --entrypoint="/bin/sh" demo-httpd:latest -c "ls -1 /var/lib/apt/lists | wc -l"
  [ $status -eq 0 ]
  [ "$output" = "0" ]
}

Execute the BATS tests:

$ bats test
  apt lists are empty
  Apache version is correct

2 tests, 0 failures

Using Makefile to glue it all together

Now this whole process might be a bit tedious in CI, with some additional steps needed before the testing is done (the image needs to be built and made available before it is tested, for example). Let's create a Makefile that will take care of the prerequisites for us:

test: bats

bats: build
  bats test

build:
  docker-compose build

Now when you execute the make test command, it will launch the bats suite, which itself depends on building the image by docker-compose—a much simpler command to integrate in the CI system of your choice:

$ make test
docker-compose build
Building http
Step 1 : FROM debian:stable-slim
 ---> d2103c196fde
[...]
Successfully built 1c4f46316f19
bats test
 
. apt lists are empty
. Apache version is correct
 2 tests, 0 failures

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.35.58