Skip to main content

🧪 testing-containers

PyPI CI License: MIT

Lightweight Python utilities for running ephemeral Docker containers in tests. Includes TestingPostgres for disposable PostgreSQL test databases and DockerContainer for ad-hoc containers.


🚀 Overview

testing-containers helps you run real services inside Docker for integration or functional tests — without ever needing to manually start external databases, message brokers or anything else.

It provides:

  • TestingPostgres — a PostgreSQL-specific helper that automatically creates a fresh empty test database before tests start and tears it down afterwards.
  • DockerContainer — a generic helper to start, stop, and execute commands inside any Docker container (Postgres, Redis, LocalStack, etc.).

The goal is simple:

Make your tests fully isolated, reproducible, and environment-agnostic — no shared state, no external dependencies.


🧭 Design Principles

  • 🧩 No external services need to be manually started
  • 🔁 Fresh empty databases are created every test run
  • 🧹 Automatic cleanup when tests finish
  • 🧱 No pollution of your dev DB — tests never touch your development data
  • ⚙️ Consistent environments — use the same database version as production via Docker
  • 🧰 Generic & extensible — same approach works for PostgreSQL, Redis, LocalStack, RabbitMQ, etc.
  • 🐳 Only dependency: Docker (required only when containers are used)

⚙️ Installation

pip install testing-containers

Requires Docker installed and running if you plan to spin up containerized services.

💡 Usage

TestingPostgres

You can use TestingPostgres in two ways

a) Run Postgres inside Docker

import psycopg
from testing_containers import TestingPostgres, ContainerOptions

pg = TestingPostgres(
    options=ContainerOptions(
        namespace="myproject-name" # optional – you can add a namespace to the container
        name="testdb" # optional – you can give a name to the container
        image="postgres:15.6" # optional / default postgres:16.3
        # The following options defines what should happen on stop()
        # container will stop or not
        # container will be removed or not
        # (you can decide on the speed you want on test startup and teardown)
        should_stop=True # optional / default=False
        remove_on_stop=True # optional / default=False
    )
)  # spins up a postgres:16.3 container
testdb = pg.postgres.testdb  # connection info for your test DB

# Connect and run migrations or tests
conn = psycopg.connect(
    dbname=testdb.name,
    user=testdb.user,
    password=testdb.password,
    host=testdb.host,
    port=testdb.port,
)
print("Connected:", conn)

# After tests
pg.stop()

b) Connect to an existing Postgres instance

❗ Important: In case the provided database is not available/ready it will spin a postgres container and use that as a fallback

from testing_containers import TestingPostgres, DBConfig

dev_db_config = DBConfig(
    host="localhost",
    name="dev_db",
    user="postgres",
    password="secret",
    port=5432,
)
pg = TestingPostgres(db_config=dev_db_config)
print(pg.testdb)  # e.g. "test_dev_db" — a fresh copy created on the fly
# ... run tests ...
pg.stop()  # drops the test DB

✅ Each run creates a temporary database (test_<original_dbname>) and destroys it afterwards.

Example: using pytests, alembic and settings on conftest

  • You run TestingPostgres
  • You mock DB environment variables to the one of TestingPostgres().postgres.test_db
  • So your app during tests runtime will be connected to testdb
  • Create a pytest fixture which run alembic migration on start and stops testdb(drops testdb) on teardown
import os
import pytest
from unittest.mock import patch
from alembic import command
from alembic.config import Config
from testing_containers import TestingPostgres

testing = TestingPostgres()
testdb = testing.postgres.test_db

env_vars = {
    "DB__USER": testdb.db.user,
    "DB__PASSWORD": testdb.db.password,
    "DB__HOST": testdb.db.host,
    "DB__PORT": str(testdb.db.port),
    "DB__NAME": testdb.db.name,
}
with patch.dict(os.environ, env_vars):
    from app.settings import settings


@pytest.fixture(scope="session", autouse=True)
def setup_test_db():
    """Setup and teardown for the test db"""
    # Run Alembic migrations
    # Ensure the path to alembic.ini is correct
    alembic_cfg = Config("alembic.ini")
    try:
        command.upgrade(alembic_cfg, "head")
    except Exception:
        raise

    yield

    testdb.stop() # Tear down test db

Generic DockerContainer

Start any service container on demand — e.g. Redis:

from testing_containers import DockerContainer

redis = DockerContainer(
    container_name="test-redis",
    image="redis:7",
    expose_ports=["6379:6379"]
)

redis.start_container()
result = redis.exec(["redis-cli", "ping"])
print(result.stdout.strip())  # → PONG
redis.stop_container()
redis.remove_container()

✅ Great for spinning up ad-hoc containers for any dependency during tests.

🧠 Why use this

Problem Solution
🧩 Tests depend on manually started external services TestingPostgres and DockerContainer spin up Docker containers automatically for your tests.
🧹 Test data pollutes your development database Each test run uses a fresh, isolated test database, which is dropped when tests finish.
⚙️ Local database version differs from production Run your tests inside Docker using the same version as production (e.g. postgres:16.3).
🧱 CI/CD pipelines need reproducible environments Works seamlessly in CI — no extra setup; containers are created and torn down automatically.
🚀 You need Redis, LocalStack, or any other service DockerContainer can run any Docker image, not just databases.
🧪 You want clean, reliable integration tests Ensures tests always start from a known empty state — no shared data, no side effects.

🧪 Requirements

  • Python 3.10+
  • Docker (required only for containerized tests)

💡 Inspiration

This project was inspired by testing.postgresql package, which provides temporary PostgreSQL instances for testing.

However, testing.postgresql requires PostgreSQL to be installed locally on the developer’s machine. That can lead to common issues in real-world teams:

  • Developers might have different PostgreSQL versions installed.
  • Local PostgreSQL configuration may differ from the production environment.
  • Installing or managing Postgres locally can be slow or error-prone in CI and requires additional setup

testing-containers solves these problems by leveraging Docker:

  • No local Postgres installation required.
  • The same Postgres (or Redis, MariaDB, etc.) version used in production can be pulled and run in tests.
  • Works identically on any environment — macOS, Linux, Windows, or CI/CD runners.

In short, it keeps the convenience of testing.postgresql while ensuring environment parity and zero setup.

🧾 License

MIT © Tedi Cela

Metadata

Release files for testing-containers 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for testing-containers 0.3.1
File Size Uploaded Provenance Actions
testing_containers-0.3.1.tar.gz 11.4 kB With provenance Details for testing_containers-0.3.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for testing-containers 0.3.1
File Interpreter ABI Platform Actions
testing_containers-0.3.1-py3-none-any.whl Python 3 none any Details for testing_containers-0.3.1-py3-none-any.whl

Total release size: 22.1 kB

Release files / testing_containers-0.3.1.tar.gz

Download URL testing_containers-0.3.1.tar.gz
Size 11.4 kB
Tags Source
SHA-256 checksum
How to use checksums
d39db8ff142eb6a820644c211ca8cbda56af5003a56db87f4267e1f2b6992d70
BLAKE2b-256 checksum
How to use checksums
c85a59209abd4def5d6aa708131de41c0b4e3d89e2f659df8299e2287532b86c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2025.

Transparency log

Release files / testing_containers-0.3.1-py3-none-any.whl

Download URL testing_containers-0.3.1-py3-none-any.whl
Size 10.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a799da389178bca34e812621d9ebf45c224117f22814fee3a5c30f7af01d4702
BLAKE2b-256 checksum
How to use checksums
a013c7974e457e3bf075d5e659eec1c72e05f472ce5290f32837c31c89fd26a1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2025.

Transparency log

Security for testing-containers 0.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for testing_containers-0.3.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2025.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page