Docker to the Rescue: Writing Lightweight Integration Tests

Docker to the Rescue: Writing Lightweight Integration Tests

Photo credit: maijou2501 via Foter.com / CC BY-SA

To show your ads properly, we at GetIntent ensure that our ad platform is reliable and trouble-proof. The reliability of the system depends on such things as the hardware type, system or network configuration, and application architecture.

Introducing changes to complex, distributed applications always entails some risk. To minimize these risks, developers write unit and integration tests. While there’s usually no difficulty writing unit tests, creating integration tests, especially sophisticated ones, can be rather demanding.

When challenges arise

Using Tomcat or Jetty for testing is no problem since, written in Java, these servers can be easily embedded. But dealing with Aerospike, which is our case, the database integration testing implies the following challenges:

  • Not written in Java, Aerospike can’t be integrated into our application effortlessly.
  • It is desirable that a developer run tests on all popular platforms including Windows, OS X, or Linux. Aerospike, however, provides binaries for Linux only.
  • Tests can be run synchronously, so do we need more servers?
  • For each test there should be a separate database instance.

In such a case, to run integration tests, shared test environment (e.g. a remote server with a configured Aerospike) is often used. Nonetheless, this approach has certain drawbacks:

  • Running tests on a remote server takes more time than running a local test. This is particularly noticeable when dealing with slow internet.
  • There might be data isolation issues in case several developers decide to test the application simultaneously.
  • Quite often, to comply with the information security policy, a company shall hide the server behind the corporate VPN. The idea of setting up a VPN client doesn’t sound encouraging when you are working from home, does it?

An alternative to this method would be preparing the local environment for testing, writing long instructions on installing and configuring Aerospike for Windows, Mac, and Linux. But there is another option — using automation tools, such as Docker.

Docker comes to help

Docker is a system used to deploy and manage applications in an isolated environment (containers). It is built on the client server architecture principles, with Docker Client available for all major operating systems and Docker Daemon run only on Linux. But the latter is no trouble: using Docker Machine you can run Docker on Windows or OS X as well, though on a virtual host.

So, to start the test, a developer needs a machine with a configured Docker Client, which is checked with a command: docker run hello-world. For Windows and OS X, Docker Machine should be installed.

Embedded Aerospike

To use Aerospike in integration tests, we created a wrapper for Docker and Docker Machine that can:

  • Start and stop containers;
  • Mount the configuration file aerospike.conf inside the container;
  • Bind a container port to the free host port;
  • Start and stop Docker Machine if testing is run on Windows or OS X.

To manage the containers, we use a popular Java Docker API Client. To start an Aerospike server within a Docker container, to configure port forwarding and mount the configuration file, we use the following command:

docker run -d -P -p 3000:3000 -v
path/to/aerospike.conf:/etc/aerospike/aerospike.conf — name aerospike aerospike

And here is the code to do the same thing using Docker Remote Api:

Writing a test

Let’s take an integration test using the embedded Aerospike as an example. Suppose we have SimpleAerospikeClient class that is able to store and retrieve user segments by ID.

View the full class.

To write a test that will check the proper implementation of these methods, we need to set up and start the server first:

Check that the data is written to and read from the database correctly.

Do not forget to stop and remove the containers created during the tests.

Conclusion

Such an approach allows running integration tests on a developer’s machine, which, in the first place, means no maintenance spending on test servers. Secondly, you can develop and test applications without access to the infrastructure.

We have reviewed a case with Aerospike, but integration tests for other services can be run in a similar way.

UPD

As a more recent and optimized way of writing integration tests we would also recommend paying attention to testcontainers-java. It’s a Java 8 library that supports JUnit tests providing lightweight, throwaway instances of common databases and Selenium web browsers.