Integration tests with Docker containers and Makefile
2 min read

Integration tests with Docker containers and Makefile

Any commercial software requires automated tests. And although there are different strategies to use, when I dived into the Go ecosystem, I came across an intriguing approach for writing integration tests.

It uses Docker images (plus docker-compose) and a Makefile to set up the environment before running the tests. In this issue, I will show a simple example of how to implement such a strategy.

Docker Compose

Let's say you have a simple CRUD service responsible for storing data to a PostgreSQL instance. In this case, it seems a good idea to validate your queries against an actual database before deploying code to production.

It is simple to start a PostgreSQL instance locally to run the application tests against it with docker and docker-compose.

#docker-compose.yaml
version: "3.8"
services:
  postgres_it:
    image: postgres
    container_name: postgres_it
    hostname: postgres
    network_mode: bridge
    ports:
      - "5432:5432"
    environment:
      POSTGRES_HOST_AUTH_METHOD: trust

With this file, we could use the docker-compose up command, and then an instance of the database would be available under localhost:5432.

Makefile

We have a single Docker image in this example, which is a straightforward environment. So running the service using the docker-compose command is not complex. But in more complex environments, extra configurations might be required.

The Makefile allows us to run a set of commands, so it's possible to start docker images, run scripts against them (like database migrations), or any option you might need.

I usually like to start by cleaning the environment and then start the needed containers again. Then, finally, we run the command to execute the application's tests.

test:
	docker-compose down
	docker-compose up -d
	go test ./...
You can also stop the containers after the test command.

Application tests

By using configuration, we make sure our integration tests are simple. Here is an example in Go.

func TestDatabaseConnection(t *testing.T) {
	ctx := context.Background()
	conn, err := pgx.Connect(ctx, "postgres://postgres@localhost:5432/postgres")
	if err != nil {
		t.Fatalf("failed to connect to database. err: %v", err)
	}

	err = conn.Ping(ctx)
	if err != nil {
		t.Fatalf("failed to ping database. err: %v", err)
	}
}

You can see it is just a matter of hitting the port exposed in the docker-compose.yaml file on localhost. Therefore, it is just a matter of running "make test" to configure the local environment and validate the application.

Conclusion

I hope this short issue gave you some perspective on what you can do if you combine Makefile and docker-compose. I've been using this approach for some time, which made me very productive.

Subscribe to the blog to get future posts, and feel free to contact me on LinkedIn or Twitter if you have any questions or suggestions.