pytest-metadata
pytest-metadata is a plugin for pytest that provides access to test session metadata. It collects system information, environment variables (especially from CI systems), and allows users to inject custom data. Currently at version 3.1.1, it is actively maintained by the pytest-dev team, with releases typically aligning with pytest compatibility and new feature additions.
Warnings
- breaking Version 2.0.0 of `pytest-metadata` dropped support for Python 2.7 and 3.6. Users on these Python versions must pin to `pytest-metadata < 2.0.0`.
- breaking Version 3.0.0 grouped CLI options. Existing automation scripts or commands that relied on specific, ungrouped command-line metadata options might need to be updated.
- gotcha When modifying session metadata within a `pytest_configure` hook, directly assigning to `config._metadata['key']` can lead to `AttributeError` if the underlying `_metadata` object is not a dictionary. The robust way to interact with `pytest-metadata`'s internal dictionary is via `config.stash[metadata_key]`.
- gotcha When running tests with `tox` in a Continuous Integration (CI) environment, environment variables (like `CI` or `BUILD_NUMBER` which `pytest-metadata` uses for auto-detection) must be explicitly passed down from the CI runner to the `tox` environment.
- gotcha Metadata is only displayed in the console report header when `pytest` is run with the `--verbose` (`-v`) flag. Without it, the metadata will still be collected and available programmatically or in reports generated by other plugins (e.g., `pytest-html`), but not shown in the standard terminal output.
Install
-
pip install pytest-metadata
Imports
- metadata_key
from pytest_metadata.plugin import metadata_key
- metadata (fixture)
def test_example(metadata): ...
- pytest_metadata (hook)
def pytest_metadata(metadata): ...
Quickstart
import pytest
import os
from pytest_metadata.plugin import metadata_key
# conftest.py (or a pytest plugin)
@pytest.hookimpl(tryfirst=True)
def pytest_configure(config):
# Initialize metadata_key if not already present (e.g., if pytest-html isn't loaded)
if not hasattr(config.stash, metadata_key):
config.stash[metadata_key] = {}
# Add custom metadata before tests run
config.stash[metadata_key]["project_name"] = "My Awesome Project"
config.stash[metadata_key]["run_by_user"] = os.environ.get("USER", "unknown")
@pytest.hookimpl(optionalhook=True)
def pytest_metadata(metadata):
# This hook modifies the final metadata dictionary that will be reported.
# For example, remove 'Packages' to simplify the report.
metadata.pop("Packages", None)
metadata["custom_value_from_hook"] = "Hello from pytest_metadata hook!"
# test_example.py
def test_access_session_metadata(metadata):
# The 'metadata' fixture provides access to the collected session metadata
print(f"\n--- Test-specific Metadata ---")
print(f"Project Name: {metadata.get('project_name')}")
print(f"Run By User: {metadata.get('run_by_user')}")
print(f"Python Version: {metadata.get('Python')}")
print(f"Custom Value: {metadata.get('custom_value_from_hook')}")
assert "project_name" in metadata
assert metadata["project_name"] == "My Awesome Project"
assert "Python" in metadata
assert "custom_value_from_hook" in metadata
# To run this example:
# 1. Save the conftest.py and test_example.py files in the same directory.
# 2. Run from your terminal:
# pytest -v --metadata cli_key cli_value --metadata another_key another_value
# Expected output will include metadata in the header (due to -v) and in the test print statements.