Skip to content
Latchkey

How to Set Up Testcontainers for Python and pytest in CI

A pytest fixture that starts a Testcontainers container and yields its connection URL keeps container lifecycle tied to the test session.

Install testcontainers (with the extra you need, e.g. testcontainers[postgres]), start the container in a @pytest.fixture, and yield the mapped host and port. GitHub-hosted runners already provide Docker.

Steps

  • Install testcontainers[postgres] in your test requirements.
  • Create a session-scoped fixture that starts the container inside a with block.
  • Yield the connection URL so tests reuse one container.
  • Run pytest on ubuntu-latest.

Fixture

conftest.py
import pytest
from testcontainers.postgres import PostgresContainer

@pytest.fixture(scope="session")
def pg_url():
    with PostgresContainer("postgres:16-alpine") as pg:
        yield pg.get_connection_url()

def test_connects(pg_url):
    assert pg_url.startswith("postgresql+psycopg2://")

Workflow

.github/workflows/ci.yml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - run: pip install -e '.[test]'
      - run: pytest -q

Gotchas

  • A session scope starts the container once for the whole run; function scope restarts it per test.
  • The with block ensures the container stops even if a test raises.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →