Skip to content

pytest infra: tests/__init__.py collision + pytest_plugins location restriction #75

Description

@antosubash

Summary

Two pytest infrastructure traps that hit every multi-module project:

  1. tests/__init__.py files cause pytest plugin-name collisions under --import-mode=importlib. When the workspace root pyproject sets addopts = "--import-mode=importlib", having modules/<m>/tests/__init__.py files in two modules makes pytest try to register tests.conftest as a plugin twice — collision error. The fix is to not create tests/__init__.py; pytest discovers test files via path walk under importlib mode.

  2. pytest_plugins = [...] in non-top-level conftest is forbidden by pytest 7.x. The framework's bundled host_conftest.py is meant to be loaded as a plugin, but if a module's conftest tries to register it via pytest_plugins, pytest raises:

    pytest_plugins variable is not allowed in non-rootdir conftest.py files
    

    Fix: register at the workspace-root conftest.py (one level above all modules) with pytest_plugins = ["host_conftest"]. Module conftests then inherit the plugin.

Reproduction

# Trap 1
echo > modules/lacowiki_legends/tests/__init__.py
echo > modules/lacowiki_datasets/tests/__init__.py
uv run pytest modules
# → "tests.conftest" plugin registered twice / import collision

# Trap 2
# In modules/lacowiki_legends/tests/conftest.py:
pytest_plugins = ["host_conftest"]
uv run pytest
# → ERROR: pytest_plugins variable is not allowed in non-rootdir conftest.py files

Workarounds

  • Don't create tests/__init__.py. Test files import via path discovery.
  • Workspace root has a single conftest.py with pytest_plugins = ["host_conftest"]. Module conftests are named conftest.py (no __init__.py parent) and just declare local fixtures.

Suggested fix

Update the framework docs / sm new scaffold to:

  1. Not create tests/__init__.py in any module template.
  2. Generate a workspace-root conftest.py with pytest_plugins = ["host_conftest"] when scaffolding a uv-workspace project.
  3. Document the importlib-mode + plugin-registration pattern prominently.

Environment

  • pytest>=8.0, pytest-asyncio>=0.24, importlib mode
  • Discovered Phases 2–5 of laco_wiki_python rewrite.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions