Skip to main content

Seamlessly run pytest tests inside docker containers

Project description

pytest-in-docker

pytest-in-docker

Teleport your pytest tests into Docker containers.

PyPI CI Python License


Install

pip install pytest-in-docker

Or with uv:

uv add pytest-in-docker

Quick Start

Decorate any test function. It runs inside a Docker container:

from pytest_in_docker import in_container

@in_container("python:alpine")
def test_runs_on_alpine():
    import platform

    info = platform.freedesktop_os_release()
    assert info["ID"] == "alpine"

Then run pytest as usual:

pytest

That's it. The function is teleported into a fresh python:alpine container, executed there, and the result is reported back to your terminal.

Usage

Marker API

If you prefer pytest markers over decorators, the plugin auto-registers @pytest.mark.in_container:

import pytest

@pytest.mark.in_container("python:alpine")
def test_mark_basic():
    import platform

    info = platform.freedesktop_os_release()
    assert info["ID"].lower() == "alpine"

The marker API integrates with all standard pytest features — fixtures, parametrize, and reporting work as expected.

Build from a Dockerfile

Point to a directory containing a Dockerfile and provide a tag. The image is built before the test runs:

from pytest_in_docker import in_container

@in_container(path="./docker", tag="my-test-image:latest")
def test_custom_image():
    import subprocess

    result = subprocess.run(["cat", "/etc/os-release"], capture_output=True, text=True)
    assert "alpine" in result.stdout.lower()

This works with the marker too:

@pytest.mark.in_container(path="./docker", tag="my-test-image:latest")
def test_custom_image_with_marker():
    ...

Test Across Multiple Images

Combine @pytest.mark.parametrize with the marker to run the same test across different containers. Use image as the parameter name — the plugin picks it up automatically:

import pytest

@pytest.mark.parametrize(
    ("image", "expected_id"),
    [
        ("python:alpine", "alpine"),
        ("python:slim", "debian"),
    ],
)
@pytest.mark.in_container()
def test_across_distros(image: str, expected_id: str):
    import platform

    info = platform.freedesktop_os_release()
    assert info["ID"].lower() == expected_id

When @pytest.mark.in_container() is called with no arguments, it reads the image parameter from @pytest.mark.parametrize. This lets you build a compatibility matrix with zero boilerplate.

How It Works

When a decorated test runs:

Host (pytest)                         Docker Container
─────────────                         ────────────────
1. Spin up container           ──────>  python:alpine starts
2. Install rpyc + pytest       ──────>  pip install rpyc pytest
3. Start RPyC server           ──────>  listening on port 51337
4. Teleport test function      ──────>  function executes here
         <────── result (pass/fail/exception) ──────
5. Container stops

The teleportation trick: RPyC can serialize a Python function and execute it on a remote interpreter. But pytest rewrites test function bytecode for better assertion messages, which breaks serialization. So before teleporting, pytest-in-docker recompiles your test from its original source code, producing a clean function that RPyC can transport.

This means:

  • Your test code runs natively inside the container — not through docker exec or shell commands
  • Full Python semantics: imports, exceptions, and return values all work naturally
  • pytest assertion introspection still works on the host side for reporting

Requirements

Requirement Version
Python >= 3.14
Docker Running on the host
pytest >= 9

Container images must have python and pip available. The official python:* images work out of the box.

API Reference

in_container(image)

Decorator. Runs the test inside a container pulled from image.

@in_container("python:3.14-slim")
def test_something():
    ...

in_container(path, tag)

Decorator. Builds an image from the Dockerfile at path, tags it as tag, then runs the test inside it.

@in_container(path="./docker", tag="my-app:test")
def test_something():
    ...

@pytest.mark.in_container(...)

Marker. Same arguments as the decorator. When called with no arguments, reads image from @pytest.mark.parametrize funcargs.

Contributing

git clone https://github.com/mesa-dot-dev/pytest-in-docker.git
cd pytest-in-docker
uv sync

Run the linter and type checker:

uv run ruff check
uv run ruff format --check
uv run pyright

Run the tests (requires Docker):

uv run pytest

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pytest_in_docker-0.1.0.tar.gz (3.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pytest_in_docker-0.1.0-py3-none-any.whl (9.0 kB view details)

Uploaded Python 3

File details

Details for the file pytest_in_docker-0.1.0.tar.gz.

File metadata

  • Download URL: pytest_in_docker-0.1.0.tar.gz
  • Upload date:
  • Size: 3.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pytest_in_docker-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d27b5732c5008e11c82556a12cbda44a739842701a70994d4c65d124afdc3a1c
MD5 aad101fbe3c396f12e8dd7763778d151
BLAKE2b-256 2dcf486ef3eef1d5d1b1bcf7d94cc362d3e028be642621610b0c195b431d02c5

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_in_docker-0.1.0.tar.gz:

Publisher: publish.yml on mesa-dot-dev/pytest-in-docker

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pytest_in_docker-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pytest_in_docker-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 706c6c41945a9a593d42a28031209439c397a6cc623de4b4a25b2a395fbd4043
MD5 35ab16293dfcb34ab1807ba208940e55
BLAKE2b-256 e7d4c77cda47a2169309e879c0afa96d1ce834c514ea2f6f6fd12e8bc44f1c1f

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_in_docker-0.1.0-py3-none-any.whl:

Publisher: publish.yml on mesa-dot-dev/pytest-in-docker

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page