Skip to main content

Run container-structure-test from pytest!

Project description

pytest-container-structure-test

PyPI - Version PyPI - Python Version pre-commit.ci status


Run container-structure-test configs from pytest, with every test in your YAML config reported as an individual pytest test — right alongside your regular Python tests.

$ pytest -v
structure.yaml::command:os-release PASSED                    [ 25%]
structure.yaml::command:gunicorn-installed PASSED            [ 50%]
structure.yaml::file-existence:app-dir PASSED                [ 75%]
test_app.py::test_healthcheck PASSED                         [100%]

Table of Contents

Installation

pip install pytest-container-structure-test

The container-structure-test binary is bundled via the container-structure-test wheel — no separate install needed. A running Docker daemon is required to execute the tests (not to collect them).

Usage

Declare your config files and the image each one targets in one place, using the container_structure_tests ini option (in pyproject.toml, pytest.ini, tox.ini, or setup.cfg). Each entry has the form <path/to/config.yaml>=<image>:

# pyproject.toml
[tool.pytest.ini_options]
container_structure_tests = [
  "tests/structure/web.yaml=myorg/web:${WEB_VERSION:-latest}",
  "tests/structure/db.yaml=${DB_IMAGE}",
  "tests/structure/cli.yaml=myorg/cli:latest",
]

Paths are relative to the pytest rootdir and must live under a directory pytest collects (typically tests/).

The image value supports environment-variable expansion, so the image name or tag can come from CI:

  • $VAR or ${VAR} — expands from the environment; referencing an unset variable is a collection error.
  • ${VAR:-default} — uses default when VAR is unset or empty, so runs work locally without exports.

Write your config files exactly as container-structure-test expects — nothing custom:

# tests/structure/web.yaml
schemaVersion: 2.0.0
commandTests:
  - name: gunicorn-installed
    command: gunicorn
    args: ["--version"]
fileExistenceTests:
  - name: app-dir
    path: /app
    shouldExist: true
metadataTest:
  exposedPorts: ["8000"]

Then just run pytest. Every entry in commandTests, fileExistenceTests, fileContentTests, and licenseTests — plus the metadataTest block — becomes its own pytest test with its own pass/fail, and failures include the errors, stdout, and stderr reported by the tool:

$ pytest -v tests/
tests/structure/web.yaml::command:gunicorn-installed PASSED
tests/structure/web.yaml::file-existence:app-dir FAILED
tests/structure/web.yaml::metadata PASSED
tests/test_app.py::test_healthcheck PASSED

=================================== FAILURES ===================================
______________________ structure/web.yaml::file-existence:app-dir _____________
File Existence Test: app-dir: FAIL
error: Expected file /app to exist but it does not

Test matrix: multiple images, configs, and platforms

When one image per config isn't enough — you want the same config against several images or architectures, or you need other container-structure-test test flags — declare suites in a plugin-owned table in pyproject.toml:

[[tool.pytest-container-structure-test.suites]]
configs   = ["tests/structure/web.yaml"]
image     = "myorg/web:${WEB_VERSION:-latest}"
platforms = ["linux/amd64", "linux/arm64"]
pull      = true

[[tool.pytest-container-structure-test.suites]]
configs    = ["tests/structure/base.yaml", "tests/structure/db.yaml"]
images     = ["${DB_IMAGE}", "myorg/db:edge"]
driver     = "docker"
extra_args = ["--save"]

Each suite expands to the cross product configs × images × platforms, and every combination is one container-structure-test invocation. When a config file runs in more than one combination, the differing dimensions show up as a suffix on each test's node ID:

tests/structure/web.yaml::command:gunicorn-installed[linux/amd64] PASSED
tests/structure/web.yaml::command:gunicorn-installed[linux/arm64] PASSED
tests/structure/db.yaml::command:psql-installed[myorg/db:edge] FAILED

Fields per suite:

Field Maps to Notes
config / configs --config one required; paths relative to rootdir
image / images --image one required; env-var expansion applies
platform / platforms --platform optional; omitted → host default
pull --pull boolean
driver --driver e.g. docker, tar, host
metadata --metadata path relative to rootdir; env-var expansion applies
extra_args passed verbatim any other flag, e.g. ["--save", "--runtime", "runsc"]

Unknown keys are rejected with a clear error (typo protection). extra_args may not include the flags the plugin itself manages (--config, --image, --platform, --output, --test-report, --no-color, --quiet) — overriding those would break result mapping.

[!NOTE] With the classic Docker image store, a tag holds one platform at a time — pulling linux/amd64 replaces a local linux/arm64 image under the same tag. When testing multiple platforms, set pull = true so each run fetches its own variant, and enable Docker's containerd image store if you want multi-platform tags cached side by side.

The simple container_structure_tests ini option keeps working and can be combined with suites; each of its entries is just a suite of one config, one image, and default flags.

How it works

  • Collection only parses the YAML — pytest --collect-only never touches Docker.
  • At run time, the binary is invoked once per config × image × platform combination and each collected test looks up its own result from that run's JSON report, so N tests in one config cost one image run per combination.
  • If the binary itself fails (Docker daemon down, image missing), every test in that config fails with the captured stderr.
  • Set PYTEST_CONTAINER_STRUCTURE_TEST_BINARY to use a different container-structure-test binary than the bundled one.

License

pytest-container-structure-test is distributed under the terms of the MIT license.

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_container_structure_test-0.0.1.tar.gz (23.3 kB view details)

Uploaded Source

Built Distribution

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

File details

Details for the file pytest_container_structure_test-0.0.1.tar.gz.

File metadata

File hashes

Hashes for pytest_container_structure_test-0.0.1.tar.gz
Algorithm Hash digest
SHA256 f58e916b0d28551b038db766971866ce5abf9f5175f0bb97fbd9667eb70cb762
MD5 7572f10a1557e477648a8506244abc81
BLAKE2b-256 f9147fa706fa0eba698d31cd0c7ba9529ccdfeee6c89f5e419ca9e7fa9685d96

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_container_structure_test-0.0.1.tar.gz:

Publisher: main.yaml on FlavioAmurrioCS/pytest-container-structure-test

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_container_structure_test-0.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for pytest_container_structure_test-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 75994c229ca1b20da896d32e8d04904bc325f2d98562cc648f5a4153f7a75f6a
MD5 1f23643dbba35d78f34a43ee269dce13
BLAKE2b-256 6da167c6008b92be83b1d44aa90eae6f9d6c24222239ee2962806cdfb1cce6c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_container_structure_test-0.0.1-py3-none-any.whl:

Publisher: main.yaml on FlavioAmurrioCS/pytest-container-structure-test

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