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.