Tutorials¶
Getting started with pytest_container¶
Note
The following tutorial demonstrates how to use
pytest_container for a Python project and to test the project’s
Command-line interface.
The example uses poetry to manage the Python
dependencies. If the pyproject.toml doesn’t already exist, create it
using the poetry init command.
Start by adding pytest_container as a development dependency:
❯ poetry add --group dev pytest_container
Add pytest-xdist, so that tests can be executed in parallel:
❯ poetry add --group dev pytest-xdist
It is recommended to create a new directory tests for your tests to keep
things tidy. Add an empty file called tests/__init__.py. Create the
tests/conftest.py file with the following contents:
from pytest_container import auto_container_parametrize
def pytest_generate_tests(metafunc):
auto_container_parametrize(metafunc)
The above code snippet ensures that the auto_container and
auto_container_per_test fixtures work correctly (that is,
they use the images defined in CONTAINER_IMAGES).
We can now implement the actual tests. We will create a simple smoke test where
we install the python wheel of our project inside a container and then check
that the installed command line utility works as expected. For that, we will
start out with the following Dockerfile. There we base our image on
openSUSE Tumbleweed, install pip into it, copy the wheel of our
python project into the image and install it in the container:
FROM registry.opensuse.org/opensuse/tumbleweed
RUN zypper -n in python3-pip
COPY dist/*whl .
RUN pip install *whl
Plug the Dockerfile into pytest_container using the
DerivedContainer class as follows:
from textwrap import dedent
from pytest_container import DerivedContainer
TW_WITH_PKG = DerivedContainer(
base="registry.opensuse.org/opensuse/tumbleweed",
containerfile=dedent("""
RUN zypper -n in python3-pip
COPY dist/*whl .
RUN pip install *whl
""")
)
Note that the FROM line is omitted from the
containerfile parameter,
as pytest_container includes it automatically.
Add the above snippet to a new file tests/test_cli.py, and add
the following test function along with a global variable:
CONTAINER_IMAGES = [TW_WITH_PKG]
def test_help_works(auto_container):
res = auto_container.connection.run_expect([0], "my-binary --help")
assert "My cool project" in res.stdout
The global variable CONTAINER_IMAGES instructs pytest_container to run
all test functions that use the auto_container or
auto_container_per_test fixtures once for each image defined in that
list. This allows you to have a single file with multiple of tests that to be
executed inside multiple container images, thus avoiding the task of
parametrizing each of the test manually.
The test function receives a
ContainerData instance, where the
connection attribute
provides a testinfra connection. The run_expect
function is used to execute the binary and check that its exit code is
0. Afterwards, we check that a search string is in the standard output.
You can now execute this test via poetry run pytest.