{"id":10156,"library":"pytestarch","title":"Pytest Arch","description":"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.","status":"active","version":"4.0.1","language":"en","source_language":"en","source_url":"https://github.com/zyskarch/pytestarch","tags":["pytest","architecture","testing","static-analysis","quality"],"install":[{"cmd":"pip install pytestarch","lang":"bash","label":"Install latest version"}],"dependencies":[],"imports":[{"note":"The primary entry point for defining architectural rules.","symbol":"architectural_rule","correct":"from pytestarch import architectural_rule"},{"note":"An alias for `architectural_rule`.","symbol":"Rule","correct":"from pytestarch import Rule"},{"note":"Used to define architectural layers in your project.","symbol":"Layer","correct":"from pytestarch.patterns import Layer"},{"note":"Helper function to collect and organize Layer objects.","symbol":"get_layers","correct":"from pytestarch.patterns import get_layers"}],"quickstart":{"code":"# Assuming a project structure like:\n# project_root/\n# ├── src/\n# │   ├── __init__.py\n# │   ├── domain/\n# │   │   ├── __init__.py\n# │   │   └── core.py\n# │   ├── application/\n# │   │   ├── __init__.py\n# │   │   └── service.py # e.g., 'from src.domain import core'\n# │   └── infrastructure/\n# │       ├── __init__.py\n# │       └── db.py # e.g., 'from src.domain import core'\n# └── tests/\n#     └── test_architecture.py\n\n# The PYTEST_ARCH_ROOT environment variable MUST be set to the path of your\n# source code root (e.g., './src') for pytestarch to discover modules correctly.\n\n# In tests/test_architecture.py\nfrom pytestarch import architectural_rule\nfrom pytestarch.patterns import Layer, get_layers\n\ndef test_layer_dependencies():\n    # Define the layers in your application.\n    # The first argument to get_layers is the base directory to scan for modules.\n    # The second argument is a list of Layer objects.\n    # Each Layer needs a unique name and a module path regex (e.g., 'src.domain').\n    layers = get_layers(\n        \"src\", # Base directory relative to where pytest is run, or an absolute path\n        [\n            Layer(\"domain\", \"src.domain\"),\n            Layer(\"application\", \"src.application\"),\n            Layer(\"infrastructure\", \"src.infrastructure\"),\n        ]\n    )\n\n    # Define architectural rules:\n    # 1. All modules discovered must belong to one of the defined layers.\n    # 2. Layers should not import modules from other layers by default.\n    # 3. Specifically, 'application' and 'infrastructure' layers are allowed\n    #    to import *only* from the 'domain' layer.\n    architectural_rule.modules_belong_to_layers(layers) \\\n        .should_not_import_modules_of_other_layers() \\\n        .may_only_import_modules_of_layers(\"domain\") \\\n        .in_layers(\"application\", \"infrastructure\") \\\n        .check()\n\n# To run this test, navigate to your project_root and execute in your terminal:\n# PYTEST_ARCH_ROOT=./src pytest tests/test_architecture.py","lang":"python","description":"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."},"warnings":[{"fix":"Review the official documentation for updated module export paths and adapt any direct imports or custom extensions as necessary.","message":"The mechanism of exporting library modules changed in v4.0.0. This could break advanced integrations or direct internal module imports that relied on previous export paths.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Upgrade your Python environment to version 3.9 or newer to ensure compatibility.","message":"Support for Python 3.8 was officially dropped in version 3.0.0. Attempting to use pytestarch v3.0.0 or later with Python 3.8 will result in compatibility errors.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Ensure `PYTEST_ARCH_ROOT` is set (e.g., `PYTEST_ARCH_ROOT=./src pytest`) to the absolute or correct relative path of your main source directory. Additionally, verify that the `root_path` argument passed to `get_layers` aligns with how your modules are imported (e.g., 'src' if your imports are `from src.module ...`).","message":"pytestarch relies heavily on the `PYTEST_ARCH_ROOT` environment variable to correctly identify the root of your source code. If this is not set or set incorrectly, module discovery and rule evaluation will fail, often leading to `ModuleNotFoundError` or `KeyError`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure your `Layer` definitions comprehensively cover all expected modules. If encountering `KeyError`, consider upgrading to v4.0.1+ and, if the issue persists, use more explicit module paths rather than overly broad regexes if necessary.","message":"Failure to include all relevant top-level modules or submodules in your `Layer` definitions, especially when using regular expressions, can lead to `KeyError` or modules being incorrectly categorized as 'not part of a layer'. This was specifically addressed for certain `KeyError` scenarios in v4.0.1.","severity":"gotcha","affected_versions":"v4.0.0"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Review your `get_layers` definitions and the regexes for each `Layer`. Ensure every top-level module (or submodule intended for a layer) has a matching `Layer` entry. Check for typos in module paths or regexes. If on v4.0.0, consider upgrading to v4.0.1+.","cause":"A module was discovered by pytestarch but does not match any defined `Layer` module path regex, or there's an internal issue with submodule import resolution (particularly in v4.0.0).","error":"KeyError: 'module_name'"},{"fix":"Either add the missing modules to an existing `Layer` definition or create a new `Layer` for them. Alternatively, if these modules should be ignored by architectural checks, use `architectural_rule.ignore_modules` to exclude them.","cause":"pytestarch found modules in your specified `root_path` (or `PYTEST_ARCH_ROOT`) that are not covered by any `Layer` definition you provided.","error":"AssertionError: The following architectural rules were violated: [... 'module.path' is not part of a layer ...]"},{"fix":"Inspect the reported import. You must either refactor the code to remove the disallowed import, or adjust your architectural rules to explicitly permit the import if it represents a valid and intended dependency.","cause":"A specific module import in your codebase violates one of the `should_not_import_modules_of_other_layers()`, `may_only_import_modules_of_layers()`, or `can_only_import_modules_of_layers()` rules you have defined.","error":"AssertionError: The following architectural rules were violated: [... 'module_a' imports from 'module_b' which is not allowed.]"},{"fix":"Ensure the `PYTEST_ARCH_ROOT` environment variable is correctly set to the absolute path of your source code directory (e.g., `export PYTEST_ARCH_ROOT=$(pwd)/src`). Also, verify that the `root_path` passed to `get_layers` matches how your modules are imported (e.g., `get_layers('src', ...)` if your imports are `from src.module`). You may also need to ensure your project root is on `PYTHONPATH` for `pytest` itself to discover modules.","cause":"pytestarch cannot find or correctly resolve your Python modules, typically because the base path (`PYTEST_ARCH_ROOT` or `root_path` in `get_layers`) is incorrect or misaligned with your project's import structure.","error":"ModuleNotFoundError: No module named 'src.your_module'"}]}