diff --git a/packages/docs-mcp/tests/__init__.py b/packages/docs-mcp/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/tapps-core/tests/__init__.py b/packages/tapps-core/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/tapps-mcp/tests/__init__.py b/packages/tapps-mcp/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pyproject.toml b/pyproject.toml index f953c143..0739818b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -187,6 +187,13 @@ testpaths = [ # passed positionally (e.g. ``pytest packages/tapps-mcp``), which overrides # testpaths. Excluding src/ keeps that invocation hermetic. norecursedirs = ["src", ".venv", "*.egg", "build", "dist", "node_modules"] +# TAP-4575: docs-mcp test modules import shared fixtures via ``from tests.helpers +# import ...``. With the tests/__init__.py files removed (so the three packages' +# identically named ``tests`` trees no longer collide under importlib), that +# import resolves only if docs-mcp's package root is on the path and ``tests`` is +# treated as a namespace package (consider_namespace_packages above). Only +# docs-mcp ships tests/helpers.py, so this is unambiguous. +pythonpath = ["packages/docs-mcp"] asyncio_mode = "auto" timeout = 60 markers = [ @@ -195,7 +202,13 @@ markers = [ "optional_deps: marks tests requiring optional dependencies (sentence-transformers, faiss-cpu, cohere)", "brain_contract: marks tests requiring a running tapps-brain HTTP server (3.18+)", ] -addopts = "-v --tb=short -p randomly --randomly-seed=last" +addopts = "-v --tb=short -p randomly --randomly-seed=last --import-mode=importlib" +# TAP-4575: importlib import mode lets the three packages' identically named +# ``tests`` trees (each ships tests/__init__.py) be collected together from the +# repo root without pytest's rootdir-based ImportPathMismatchError. Namespace +# packages must be considered so docs-mcp's ``from tests.helpers import ...`` +# still resolves under importlib mode. +consider_namespace_packages = true filterwarnings = [ "ignore:tapps_core\\.memory is deprecated:DeprecationWarning", "ignore:tapps_core\\.memory\\.gc is deprecated:DeprecationWarning", diff --git a/scripts/prepush-smoke.sh b/scripts/prepush-smoke.sh index 64a78b26..4d6fd2dc 100755 --- a/scripts/prepush-smoke.sh +++ b/scripts/prepush-smoke.sh @@ -5,8 +5,10 @@ # Intentionally avoids pytest-xdist (-n auto): parallel runs starve live Cursor # MCP child processes during push and can flake unrelated integration tests. # -# Each test path runs in its own pytest invocation to avoid conftest.py -# ImportPathMismatchError across packages. +# Each curated test path runs in its own serial pytest invocation for that +# xdist-avoidance reason. (The cross-package conftest.py ImportPathMismatchError +# that once forced separate invocations is fixed — TAP-4575 added +# --import-mode=importlib so a single root run collects all three packages.) set -euo pipefail diff --git a/scripts/run-regression.sh b/scripts/run-regression.sh index 87cad326..3a54ac69 100755 --- a/scripts/run-regression.sh +++ b/scripts/run-regression.sh @@ -15,17 +15,12 @@ if [[ "${1:-}" == "--serial" ]]; then XDIST=() fi -echo "[regression] Full non-slow suite (all packages). Not part of git push." >&2 -FAILED=0 -for PKG in packages/tapps-mcp packages/tapps-core packages/docs-mcp; do - echo "[regression] $PKG/tests/" >&2 - if ! uv run pytest "$PKG/tests/" -m "not slow" -q --tb=line --timeout=60 "${XDIST[@]}" --maxfail=3; then - FAILED=1 - fi -done - -if [[ "$FAILED" -ne 0 ]]; then - echo "[regression] FAILED — investigate with: uv run pytest /tests/ -m 'not slow' -v" >&2 +echo "[regression] Full non-slow suite (all packages, single invocation). Not part of git push." >&2 +# TAP-4575: the three packages' tests are collected in one root pytest run +# (testpaths + --import-mode=importlib in pyproject.toml). No more per-package +# loop — a single invocation restores cross-package xdist parallelism. +if ! uv run pytest -m "not slow" -q --tb=line --timeout=60 "${XDIST[@]}" --maxfail=3; then + echo "[regression] FAILED — investigate with: uv run pytest -m 'not slow' -v" >&2 exit 1 fi