Docker and managing Integration tests — A better approach.

Requirement 1

For certain test cases we need to run a docker-compose as the first step, which in turn depends on creating a few images, plus a few other custom steps.

Requirement 2

Separately being able to run tests that rely on docker under the hood, while running sbt test should ideally avoid these slow running tests.

Requirement 3

One thing I need to have is, being able to spin up the docker-compose explicitly but avoid running test cases at times. This might sound silly because isn’t it what docker-compose all about.? Yes, it is, but since we are aiming for more, we shouldn’t discard this simple feature, because it allows me to do some verifications of the containers or its filesystem manually. If compose-up is tightly coupled to the functional test cases beyond an extent, this is fairly impossible. This requirement discards DockerComposeUp within test cases. If you are looking to compose-up within test cases, then this link is going to be extremely useful:
https://github.com/testcontainers/testcontainers-scala

Requirement 4

As part of these requirements, we also prefer having the docker-compose.yml generated from sbt without polluting git history. In short, just about everything related to docker should come only through SBT. We need only 1 complexity, not more!

My philosophy on Integration Tests

Well, to be honest, apart from the simple requirements above, there are some philosophical reasons leading to some of my design choices. To make it sound more practical, I am copy pasting my own comments in the code base that I am working on. I urge you to read through them :)


Philisophy behind the design where images have built-in sample data, and test environment set up being part of build settings:
-----------------------------------------------------------------
1) The "real" environment for "real" testing shouldn't be mutated anywhere else other than the application itself. This leads to better testing of the lifecycle of an application.
2) Multiple integration tests sharing the same environment is a tragic situation. Stop reusing. Don't be lazy.3) If you want to run concurrency tests, run multiple instances of the same application with in the same test case, with obviously a test environment completely new and not being used/mutated anywhere else.4) To trouble shoot test environment, you should be able to spin up just the test environment in isolation. A build task could be a perfect solution to do this. You are building an environment that your app is supposed to work on.5) If your integration test fails, it means you don't know about the real test environment. So come back to build configs to know more about it, and change your test cases.
  • We might have done port mappings in docker-compose files
  • There is a host machine dependency for your docker environment. An example is putting a README of what to change in /etc/hosts on running integration tests, may be to run from an IDE.

Let’s start the set up now

The main concepts involved:
1) Dockerish stuffs
2) Sbt Tasks
3) Sbt Scope
4) Sbt Tags for scala test cases (with respect to Specs2 and ScalaCheck).

Step 1

Add the required plugins in plugins.sbt

addSbtPlugin("com.tapad" % "sbt-docker-compose" % "1.0.34")
addSbtPlugin("se.marcuslonnberg" % "sbt-docker" % "1.5.0")

Step 2

Let’s define a context that runs only docker related tests:

Tests.Argument(
TestFrameworks.Specs2, “include”, “DockerComposeTag”
)`

Step 3

Now the next step is to create images, create docker-compose.yml, and dockerComposeUp before we run the DockerTest . We can achieve this using the addition of another setting to the above build configuration.

Step 4

Let us see the sample DockerUtil.scala that is responsible for docker-compose up before any DockerTest is run.

Step 5

Now the final step is to write test that are tagged withDockerComposeTag.

Result:

sbt docker-int:test will run docker-compose up as the first step, and runs only IntegrationTest .

Fantastic CI

sbt dockerComposeDown dockerComposeUp docker-int:test dockerComposeDown

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Afsal Thaj

Afsal Thaj

A software engineer and a functional programming enthusiast at Simple-machines, Sydney, and a hardcore hiking fan. https://twitter.com/afsalt2