pytest-operator
pytest-operator provides a set of pytest fixtures designed to simplify the testing of Charmed Operators, particularly for integration and functional tests. It abstracts away much of the complexity of deploying and managing Juju models and charms within a test environment. The current version is 0.43.2, and it maintains an active release cadence with frequent patch updates and occasional minor feature releases.
Common errors
-
fixture 'ops_test' not found
cause The `pytest-operator` plugin is not correctly loaded by pytest. This usually happens if `pytest-operator` is not installed, or if the `pytest_plugins` declaration is missing or incorrect in `conftest.py`.fixEnsure `pytest-operator` is installed (`pip install pytest-operator`). In your `conftest.py` (or the test module itself), add `pytest_plugins = ['pytest_operator.plugin']`. -
ModuleNotFoundError: No module named 'charmcraft.juju.local'
cause This error often indicates an issue with the `charmcraft` installation or its compatibility with the Python environment, particularly if `charmcraft` was installed via `pip` instead of `snap`.fixInstall `charmcraft` via `snap`: `sudo snap install charmcraft --classic`. Avoid `pip install charmcraft` as it's not the officially supported installation method for the CLI tool. -
FileNotFoundError: [Errno 2] No such file or directory: 'charmcraft'
cause The `charmcraft` executable is not found in the system's PATH, even if it might be installed.fixVerify `charmcraft` is installed and its binary is in your system's PATH. If installed via snap, ensure snap binaries are in PATH (e.g., `export PATH=$PATH:/snap/bin`). -
AssertionError: Expected 1 application to be deployed, but found 0 (or similar deployment failure)
cause The charm deployment failed. This could be due to issues within the charm's code, incorrect charm path provided to `build_charm`, or problems with the underlying Juju environment setup by `pytest-operator`.fixCheck the charm's build log in the test output. Verify the `CHARM_ROOT` path is correct. Review Juju agent logs (`juju debug-log`) to pinpoint the issue. Ensure your test environment has necessary resources (e.g., sufficient disk space).
Warnings
- gotcha The `ops_test` fixture operates on a clean, ephemeral Juju model for each test session. Any deployments or changes made during a test run are automatically cleaned up afterward, meaning no persistent state between test runs.
- gotcha To use `ops_test.build_charm()`, `charmcraft` must be installed and accessible in your system's PATH. If `charmcraft` is not found, charm building will fail.
- gotcha Integration tests can be significantly slower than unit tests due to the overhead of building charms, deploying applications, and waiting for Juju model states.
Install
-
pip install pytest-operator
Imports
- pytest_plugins
from pytest_operator import plugin
pytest_plugins = ['pytest_operator.plugin']
Quickstart
# conftest.py
pytest_plugins = ["pytest_operator.plugin"]
# tests/integration/test_my_charm.py
import pytest
from pathlib import Path
# Assuming your charm source is in a 'src' directory relative to the tests
CHARM_ROOT = Path(__file__).parent.parent / "src"
async def test_charm_is_deployed(ops_test):
# Build the charm locally
charm = await ops_test.build_charm(CHARM_ROOT)
# Deploy the charm to the ephemeral Juju model
await ops_test.model.deploy(charm)
# Wait for the application to reach an idle state
await ops_test.model.wait_for_idle(apps=[charm.name], status="active", timeout=600)
# Assertions about the application state
assert ops_test.model.applications[charm.name].units[0].workload_status == "active"