Seamlessly run pytest tests inside docker containers
Project description
pytest-in-docker
Teleport your pytest tests into Docker containers.
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 execor 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
pythonandpipavailable. The officialpython:*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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d27b5732c5008e11c82556a12cbda44a739842701a70994d4c65d124afdc3a1c
|
|
| MD5 |
aad101fbe3c396f12e8dd7763778d151
|
|
| BLAKE2b-256 |
2dcf486ef3eef1d5d1b1bcf7d94cc362d3e028be642621610b0c195b431d02c5
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_in_docker-0.1.0.tar.gz -
Subject digest:
d27b5732c5008e11c82556a12cbda44a739842701a70994d4c65d124afdc3a1c - Sigstore transparency entry: 925801937
- Sigstore integration time:
-
Permalink:
mesa-dot-dev/pytest-in-docker@8e6da17b5b9756daa082213e9cf8a9f7a7b014eb -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mesa-dot-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8e6da17b5b9756daa082213e9cf8a9f7a7b014eb -
Trigger Event:
release
-
Statement type:
File details
Details for the file pytest_in_docker-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pytest_in_docker-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
706c6c41945a9a593d42a28031209439c397a6cc623de4b4a25b2a395fbd4043
|
|
| MD5 |
35ab16293dfcb34ab1807ba208940e55
|
|
| BLAKE2b-256 |
e7d4c77cda47a2169309e879c0afa96d1ce834c514ea2f6f6fd12e8bc44f1c1f
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_in_docker-0.1.0-py3-none-any.whl -
Subject digest:
706c6c41945a9a593d42a28031209439c397a6cc623de4b4a25b2a395fbd4043 - Sigstore transparency entry: 925801942
- Sigstore integration time:
-
Permalink:
mesa-dot-dev/pytest-in-docker@8e6da17b5b9756daa082213e9cf8a9f7a7b014eb -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mesa-dot-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8e6da17b5b9756daa082213e9cf8a9f7a7b014eb -
Trigger Event:
release
-
Statement type: