Pytest Arch

4.0.1 · active · verified Fri Apr 17

pytestarch is a Python test framework that enables static analysis of software architecture by defining and enforcing rules based on import dependencies between modules. It integrates seamlessly with pytest to ensure architectural constraints are met. The current version is 4.0.1, with major releases occurring periodically to introduce new features and adapt to Python version changes.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to define and verify architectural layer dependencies using `pytestarch`. It assumes a standard Python project layout with a `src/` directory containing your modules and a `tests/` directory for your `pytestarch` test files. The `PYTEST_ARCH_ROOT` environment variable is crucial for module discovery.

# Assuming a project structure like:
# project_root/
# ├── src/
# │   ├── __init__.py
# │   ├── domain/
# │   │   ├── __init__.py
# │   │   └── core.py
# │   ├── application/
# │   │   ├── __init__.py
# │   │   └── service.py # e.g., 'from src.domain import core'
# │   └── infrastructure/
# │       ├── __init__.py
# │       └── db.py # e.g., 'from src.domain import core'
# └── tests/
#     └── test_architecture.py

# The PYTEST_ARCH_ROOT environment variable MUST be set to the path of your
# source code root (e.g., './src') for pytestarch to discover modules correctly.

# In tests/test_architecture.py
from pytestarch import architectural_rule
from pytestarch.patterns import Layer, get_layers

def test_layer_dependencies():
    # Define the layers in your application.
    # The first argument to get_layers is the base directory to scan for modules.
    # The second argument is a list of Layer objects.
    # Each Layer needs a unique name and a module path regex (e.g., 'src.domain').
    layers = get_layers(
        "src", # Base directory relative to where pytest is run, or an absolute path
        [
            Layer("domain", "src.domain"),
            Layer("application", "src.application"),
            Layer("infrastructure", "src.infrastructure"),
        ]
    )

    # Define architectural rules:
    # 1. All modules discovered must belong to one of the defined layers.
    # 2. Layers should not import modules from other layers by default.
    # 3. Specifically, 'application' and 'infrastructure' layers are allowed
    #    to import *only* from the 'domain' layer.
    architectural_rule.modules_belong_to_layers(layers) \
        .should_not_import_modules_of_other_layers() \
        .may_only_import_modules_of_layers("domain") \
        .in_layers("application", "infrastructure") \
        .check()

# To run this test, navigate to your project_root and execute in your terminal:
# PYTEST_ARCH_ROOT=./src pytest tests/test_architecture.py

view raw JSON →