Test-Driven Development addresses the issue of doing local, small-scope testing as part of implementation. However, it doesn’t address issues related to the system as a whole, or that might only occur when components are integrated.

Martin Folwer introduced the term continuous integration to describe a system where we also perform integration testing at least once pr day.

The fundamental benefit of continuous integration is that it removes sessions where people spend time hunting bugs where one person’s work has stepped on someone else’s work without either person realizing what happened. These bugs are hard to find because the problem isn’t in one person’s area, it is in the interaction between two pieces of work.

– Fowler, 2000.

A system that supports continuous integration needs, at a minimum, the following capabilities:

  • It requires a revision control system, with a centralized main revision that can be used.
  • The build process should be automated so that anyone can manually launch the process. [it should also support automated testing based on other events, like integrating a branch in the source tree].
  • Tests should be automated so that they can be launched manually as well.
  • The system should produce a final distribution.

CI Systems

Continuous Integration Systems are software systems that provide these capabilities. Early standalone systems include Jenkins (Open Source), and CircleCI. Many source control platforms also provide CI functionality, including Bitbucket, GitHub and GitLab.

For example, you can automate GitLab so that it will build and run your tests anytime a specific action is performed like committing to a branch, or merging a PR. This is managed through the CI/CD section of the project configuration.

GitLab CI GitLab CI

The GitLab configuration and terminology is pretty standard:

  • A pipeline represents the work or the job that will be done.
  • A stage represents a set of jobs that need to be executed together.
  • Jobs are executed by runners, which define and where a job will be executed.

These all represent actions that will be taken against your source code repository at specific times. The examples that they provide include:

  • A build stage, with a job called compile.
  • A test stage, with two jobs called test1 and test2.
  • A staging stage, with a job called deploy-to-stage.
  • A production stage, with a job called deploy-to-prod.

In this way, you can setup your source code repository to build, test, stage and deploy your software automatically one or more times per day, as a result of some key event, or when manually executed.


Although we have a GitLab instance running, we do not have access to a cluster that can run jobs for us. In other words, we cannot do this in production using our current setup – at least not without gaining access to a Kubernetes cluster somewhere.