Skip to content

Latest commit

 

History

History
40 lines (25 loc) · 1.99 KB

File metadata and controls

40 lines (25 loc) · 1.99 KB

Test layout

Overview

Tests live in two places:

  • Cross-package suites under the root tests/ directory (contract, logs, config, integration, etc.).
  • Package-local suites under each workspace member's tests/ directory (e.g. packages/core/tests/, apps/gateway/tests/).

Pytest discovers both via testpaths = ["tests", "packages"] in pyproject.toml and resolves imports through the pythonpath list under [tool.pytest.ini_options], which already names every package's src/ directory.

Convention: no __init__.py in package-local test dirs

Package-local test directories (packages/*/tests/, apps/*/tests/) must not contain an __init__.py.

The cross-package suites under the root tests/ tree do use __init__.py (one per subdirectory) because they form a coherent tests.* namespace.

Why

Pytest is configured with --import-mode=importlib, so it does not require __init__.py to collect test modules. But mypy walks the directory tree by package name. Without --explicit-package-bases, two sibling __init__.py files named tests/__init__.py (e.g. packages/core/tests/__init__.py and apps/gateway/tests/__init__.py) both resolve to the top-level module name tests and collide:

apps/gateway/tests/__init__.py: error: Duplicate module named "tests"
(also at "packages/core/tests/__init__.py")

Mypy bails out on the duplicate before it checks any source code, which silently disables task lint / make lint for the whole repo. Omitting __init__.py from package-local test dirs sidesteps the collision without giving up strict mode anywhere else.

How to apply

When adding a new package, scaffold its tests like this:

packages/my-pkg/
└── tests/
    ├── test_foo.py        # no __init__.py here
    └── test_bar.py

The existing pythonpath list in pyproject.toml already covers every workspace member's src/, so test modules can import rag_my_pkg directly without any additional configuration.