Docker widely used in the development environment, and one of the usages is testing.
This article will focus on two different usages of Docker for Golang tests:
1. Use Docker image to test and build your application
2. Use Go package to set up and run Docker images programmatically
During this article, we will use MongoCLI open-source repository as an example. Consider checking it out.
Docker image for your application.
Having a Docker image for your application is quite straightforward and commonly used approach. It gives you isolation from your local machine and can be run anywhere where you have Docker installed. We can apply the same technics to any other programming language. Also, we can have one image for the back-end and another for the front-end.
Here is an example Docker image (also taken from mongocli):
RUN mkdir /app
ADD . /app/
RUN go test -v ./...
RUN go build -o mongocli mongocli.go
RUN touch ~/mongocli.yml
RUN echo -e "Server: db\nPort: 27017" > ~/mongocli.yml
RUN touch mongocli.yml
Here we use an official Go image as a base: golang:latest. Then we set-up our environment and run tests. Once all tests passed, we build our application and save it as the mongocli executable file.
We can build and run this image using the following command:
docker build -f Dockerfile -t mongocli:latest .
docker run mongocli:latest
Also, we can execute our mongocli application from within Docker container:
docker run mongocli:latest mongocli help
Go package dockertest to manage containers during the tests
For this approach, we will need an external package. There are a few of Go packages for this purpose. In this article, I will focus on dockertest:
Use Docker to run your Go language integration tests against third party services on Microsoft Windows, Mac OSX and…
Let’s start with a code:
As you can see, we have TestMain as an entry point for our tests. In this function, we initialize an instance of dockertest’s Pool and try to spawn up MongoDB container.
If the initialization of the container went successful, we get the port number for MongoDB and create an instance of our tested object — mc (line 38) — and run test command — Ping (line 39).
Once we have successful preparation, we keep a global instance of the needed object (mc, line 13) and pass execution flow to a required test.
Both approaches work well. But there is one mention-worthy point. Theoretically, if with case one, you can have a bunch of tests and call them unit tests, however, in case two, it will be very questionable if you can call the same tests unit tests when you have an external dependency like, for example, MongoDB. Details of this statement are probably for the next article. Until then, happy coding!