Golang Integration Testing Made Easy

How we at Gojek implement integration testing in our development processes.

Arie Ardaya Lizuardi
Gojek Product + Tech
5 min readSep 15, 2020

--

At Gojek, integration tests play a big role in our software development practices. This ensures that multiple parts of our application work together as expected and helps us meticulously solve problems.

In this blog, I’ll share nitty-gritties about the integration testing approach we implement in our daily software development process — especially backend development.

While this approach could be implemented in different programming languages, the flow helps us solve issues such as:

  • Absence of mocking library for that particular dependency. In my case, it was Apache Kafka or when I wanted to test Redis and there was no mocking library for the development language I used.
  • Even when there is a mocking library, situations where we want to make sure the query is sent correctly to the DB or when we use caching and want to ensure the cache is created/deleted.

Our Approach

The diagram above describes the flow of our integration testing. We utilise Makefile and docker-compose as our tools. Makefile simplifies testing command execution and Docker compose helps us run multiple containers that we use in our application. The flow would look like this:

Step-1: Create Makefile commands. This sets up our basic testing commands.

Step-2: Create or edit docker-compose.yaml. This defines application dependencies (DB, cache, message broker, etc). You can edit your docker-compose.yaml if you have a new dependency.

Step-3: Create an integration testing code in your favourite language.

Step-4: Execute the test command.

If you have a new use case to test, just repeat Step 3 and 4.

Let’s jump into an example.

Say we have a blog backend API server that will save an article, get articles by id, and get all articles. We will have an end to end test for the whole application flow and also the database interaction test. This is how our folder structure would look like:

[Note: Some folders and files are omitted]

├── article
│ ├── handler
│ ├── repository
│ │ └── article_postgres.go
│ ├── usecase
├── it
│ ├── article_repository_test.go
│ ├── e2e_test.go
│ ├── it.go
│ └── postgres_suite_test.go
├── server
│ ├── server.go

The code inside the server package will have a dependency on the handler, use case, and repository. The end to end testing will spawn the server, and we’ll send some requests and assert the response. The database interaction test will assert the method inside the repository package. You can find the full source code below:

The server code:

The database interaction code inside the repository package:

Create Makefile commands

Originally, Makefile is not only used to list out a set of directions to compile C or C++files, but also for other purposes. In our case, we list out a set of directives for our integration testing commands.

If you’re not too familiar with Makefile, check out this and this to get a better understanding.

Open your command-line interface

The Makefile will look like this

Create docker-compose.yml

Docker compose will help us run multiple Docker containers easily. We will configure our docker dependencies in the YAML file. If you have not installed docker-compose, you can install it from this link.

This configuration tells docker-compose to run Postgres image. You can add other images depending on your use case.

Create integration test code

Now, we need to create integration testing for the above code. Let’s create e2e_test.go and article_repository_test.go file under it folder.

Execute test integration command from your CLI

You will see something like this:

Voila! We just finish our integration testing. 🖖

Want to read more stories from the vault? Check out our blogs!

--

--