Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 66 additions & 80 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,99 +1,85 @@
"""
Pytest configuration and fixtures for BioAnalyzer tests.
This module automatically configures Python path for both Docker and local environments.
Pytest configuration for BioAnalyzer tests.

This file ensures the `app` package is importable in both local and Docker
environments by configuring `sys.path` and `PYTHONPATH`.

It also re-applies the configuration during pytest startup and collection,
since pytest may adjust import paths.
"""

import sys
import os
import sys
from pathlib import Path

# Get the project root (parent of tests directory)
project_root = Path(__file__).parent.parent
project_root_str = str(project_root.resolve())

# Detect if we're running in Docker (check if /app exists and is a directory)
is_docker = Path("/app").exists() and Path("/app").is_dir()

# Configure Python path based on environment
paths_to_add = []

if is_docker:
# Docker environment: code is at /app/
# Add /app first (this is where app/ package is located)
docker_paths = ["/app"]
for path in docker_paths:
if path not in sys.path:
paths_to_add.append(path)
else:
# Local environment: code is at project root
# Add project root (this is where app/ package is located)
if project_root_str not in sys.path:
paths_to_add.append(project_root_str)

# Add paths to sys.path (insert at beginning for priority)
for path in paths_to_add:
sys.path.insert(0, path)

# Also ensure project root is always in path (works for both environments)
if project_root_str not in sys.path:
sys.path.insert(0, project_root_str)

# Update PYTHONPATH environment variable
existing_pythonpath = os.environ.get("PYTHONPATH", "")
pythonpath_parts = [p for p in existing_pythonpath.split(":") if p]
for path in paths_to_add + [project_root_str]:
if path not in pythonpath_parts:
pythonpath_parts.insert(0, path)
os.environ["PYTHONPATH"] = ":".join(pythonpath_parts)

# Verify we can import app
try:
import app
except ImportError:
# If import fails, try adding common paths
fallback_paths = [
project_root_str,
str(project_root / "app"),
"/app",
"/app/app",
]
for path in fallback_paths:
if Path(path).exists() and path not in sys.path:
sys.path.insert(0, path)
try:
import app
PROJECT_ROOT = Path(__file__).parent.parent.resolve()
PROJECT_ROOT_STR = str(PROJECT_ROOT)

IS_DOCKER = Path("/app").is_dir()

DOCKER_PATHS = ["/app"]
FALLBACK_PATHS = [
PROJECT_ROOT_STR,
str(PROJECT_ROOT / "app"),
"/app",
"/app/app",
]


break
def _ensure_paths() -> None:
"""Ensure required paths exist in sys.path and PYTHONPATH."""
paths = DOCKER_PATHS if IS_DOCKER else []
paths = paths + [PROJECT_ROOT_STR]

# sys.path
for p in reversed(paths): # reversed so first item ends up at index 0
if p not in sys.path:
sys.path.insert(0, p)

# PYTHONPATH
existing = os.environ.get("PYTHONPATH", "")
parts = [p for p in existing.split(":") if p]
for p in reversed(paths):
if p not in parts:
parts.insert(0, p)
os.environ["PYTHONPATH"] = ":".join(parts)


def _ensure_app_importable() -> None:
"""Try importing app; if it fails, try common fallback paths."""
try:
import app # noqa: F401
return
except ImportError:
pass

for p in FALLBACK_PATHS:
if Path(p).exists() and p not in sys.path:
sys.path.insert(0, p)
try:
import app # noqa: F401
return
except ImportError:
continue


# Apply immediately when conftest is imported
_ensure_paths()
_ensure_app_importable()


def pytest_configure(config):
"""Configure pytest - runs before test collection."""
# Re-ensure paths are set (pytest may reset them)
if is_docker:
docker_paths = ["/app"]
for path in docker_paths:
if path not in sys.path:
sys.path.insert(0, path)

if project_root_str not in sys.path:
sys.path.insert(0, project_root_str)

# Verify app can be imported
"""Runs before test collection."""
_ensure_paths()
try:
import app
import app # noqa: F401
except ImportError as e:
print(f"WARNING: Cannot import app module: {e}")
print(f"Python path: {sys.path}")
print(f"Project root: {project_root_str}")
print(f"Is Docker: {is_docker}")
print(f"Project root: {PROJECT_ROOT_STR}")
print(f"Is Docker: {IS_DOCKER}")


def pytest_collection_modifyitems(config, items):
"""Hook that runs after collection but before test execution."""
# Ensure path is set (redundant but safe)
if project_root_str not in sys.path:
sys.path.insert(0, project_root_str)
if is_docker and "/app" not in sys.path:
sys.path.insert(0, "/app")
"""Runs after collection but before test execution."""
_ensure_paths()
Loading