An example of how to run Testcontainers in CI pipelines. This example is using GitHub Actions, but the same ideas apply to other CI pipeline runners too.
Based on tomodachi-testcontainers and testcontainers-python.
To run Testcontainers in the CI pipeline, you'll need a container runtime installed on the CI server (GitHub Actions, Jenkins etc.). That's pretty much it!
Running Testcontainers in the CI shouldn't be much different from running them locally.
This example is using GitHub Actions, where the ubuntu-latest
image has Docker Engine
pre-installed, so no extra setup is needed.
Generally there're could be (probably there are more!) two approaches for running tests in CI pipelines:
Install programming language runtime and dependencies on the CI server, and run the tests directly on the CI server too. This approach example pipeline is in .github/workflows/build-and-test--on-ci-server.yml
- That's very similar to how tests are run on a local machine.
- This works really well with GitHub Actions, because after the workflow is finished, CI server is discarded and all the installed dependencies are removed, so the next workflow run starts from a clean state.
- A downside for this approach: tests won't be running in the exactly the same environment as the production environment. To fix this, we can run the tests from inside the application's Docker container - the deployment environment.
The application code, its dependencies and the test suite are first packaged into a Docker image, and the tests are run from inside the Docker container.
This approach example pipeline is in .github/workflows/build-and-test--with-dev-image.yml
-
CI server only needs a container runtime installed, no other dependencies are needed.
-
It usually requires a multi-stage Dockerfile with two stages:
Development
- with development dependencies installed.Release
- with only production dependencies and production code.
-
This approach isolates how the tests are run from the mechanics of the specific CI server you're using - the tests are always run in the same way, in exactly the same environment as production, because it's the same Docker image.
-
How it works:
- CI server runs a Docker image from the
development
stage, and runs the test command in the container. - However, since the application itself is tested as a (test)container, the container that's running the tests must be able to run new Docker containers.
- This can be done with "Docker-from-Docker" method by mounting the Docker Unix socket from the host machine to the container. It will allow a container to run new containers on the host machine.
⚠️ In the end-to-end tests, we want to test the exact same Docker image that's going to be deployed to production, so the tests must be ran against therelease
stage Docker image.- In case of tomodachi-testcontainers,
use the environment variable
TOMODACHI_TESTCONTAINER_IMAGE_ID
to specify the image ID of therelease
stage.
- CI server runs a Docker image from the
- Install dev dependencies with Poetry
poetry install
poetry shell
pre-commit install
- Run tests
poetry run test
poetry run test-ci
- Format and lint code
poetry run format
poetry run lint
- Run all commit hooks at once
poetry run hooks