pytest-docker
pytest-docker provides simple pytest fixtures for testing applications that rely on Docker or Docker Compose services. It simplifies the setup and teardown of Docker containers or multi-container applications (defined via `docker-compose.yml`) for integration tests, automatically managing their lifecycle. The current version is 3.2.5, and it maintains an active release cadence with frequent updates.
Warnings
- breaking Version 3.0.0 introduced a breaking change by dropping support for Python 3.6 and 3.7. Python 3.8+ is now required, alongside compatibility with pytest v8.
- gotcha The `docker-compose` Python library dependency version is conditional on your Python interpreter. For Python versions below 3.10, `docker-compose` version 1.x is required. For Python 3.10 and newer, `docker-compose` version 2.x is required. Incorrect versions can lead to `ImportError` or unexpected behavior.
- gotcha As of v3.2.5, the default `docker_setup_command` for `docker_compose` now includes `--wait`. This command blocks until all services are 'healthy' according to their `healthcheck` definitions. This can significantly increase service startup time during tests if healthchecks are slow or improperly configured.
- gotcha The `docker_setup_command` fixture was fixed in v3.2.1 to correctly reference `docker_setup`. Users who might have manually overridden `docker_setup_command` in older versions should verify their fixture names and implementations for compatibility.
- gotcha The Docker daemon must be running and accessible for `pytest-docker` to function. This library does not manage the Docker daemon itself, only the containers/services it orchestrates.
Install
-
pip install pytest-docker -
pip install pytest-docker 'docker-compose>=2.0.0; python_version >= "3.10"' 'docker-compose<2.0; python_version < "3.10"'
Imports
- docker_compose
def test_something(docker_compose): # Access services via docker_compose fixture ... - docker_client
def test_something(docker_client): # Access Docker client via docker_client fixture ... - docker_compose_file
import pytest from pathlib import Path @pytest.fixture(scope="session") def docker_compose_file(): return str(Path(__file__).parent / "docker-compose.yml") - Services
from pytest_docker.plugin import Services def my_test_function(docker_compose: Services): # Use for type hinting the docker_compose fixture ...
Quickstart
import pytest
import redis
import time
from pathlib import Path
# This fixture tells pytest-docker where to find docker-compose.yml.
# Place this in your conftest.py or directly in your test file.
@pytest.fixture(scope="session")
def docker_compose_file():
# Assumes docker-compose.yml is in the same directory as this test file.
return str(Path(__file__).parent / "docker-compose.yml")
def test_redis_connection(docker_compose):
# The 'docker_compose' fixture automatically starts services from docker-compose.yml
# Get the host and exposed port for the 'redis' service
host, port = docker_compose.get_service_host_port("redis", 6379)
# Poll until the Redis service is ready to accept connections
_redis_client = None
for _ in range(30): # Try for up to 30 seconds
try:
_redis_client = redis.Redis(host=host, port=port, decode_responses=True)
_redis_client.ping() # Check connection
break
except redis.exceptions.ConnectionError:
time.sleep(1)
else:
pytest.fail("Redis service not ready after 30 seconds")
assert _redis_client is not None
_redis_client.set("mykey", "myvalue")
assert _redis_client.get("mykey") == "myvalue"
_redis_client.close()