diff --git a/.gitignore b/.gitignore index 29d56f25..65ed7e18 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,6 @@ www/REFACTOR.md www/reload-frontend server/test.sqlite CLAUDE.local.md +./www/.pnpm-store www/.env.development www/.env.production diff --git a/CLAUDE.md b/CLAUDE.md index 14c58e42..c3032905 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -42,13 +42,13 @@ uv run celery -A reflector.worker.app beat **Testing:** ```bash # Run all tests with coverage -uv run pytest +REDIS_HOST=localhost CELERY_BROKER_URL=redis://localhost:6379/1 CELERY_RESULT_BACKEND=redis://localhost:6379/1 uv run pytest # Run specific test file -uv run pytest tests/test_transcripts.py +REDIS_HOST=localhost CELERY_BROKER_URL=redis://localhost:6379/1 CELERY_RESULT_BACKEND=redis://localhost:6379/1 uv run pytest tests/test_transcripts.py # Run tests with verbose output -uv run pytest -v +REDIS_HOST=localhost CELERY_BROKER_URL=redis://localhost:6379/1 CELERY_RESULT_BACKEND=redis://localhost:6379/1 uv run pytest -v ``` **Process Audio Files:** diff --git a/server/tests/conftest.py b/server/tests/conftest.py index d739751d..4694c08b 100644 --- a/server/tests/conftest.py +++ b/server/tests/conftest.py @@ -1,4 +1,5 @@ import os +import subprocess from tempfile import NamedTemporaryFile from unittest.mock import patch @@ -27,16 +28,63 @@ def vcr_config(): "filter_headers": [("authorization", "DUMMY_API_KEY")], } - @pytest.fixture(scope="session") def docker_compose_file(pytestconfig): return os.path.join(str(pytestconfig.rootdir), "tests", "docker-compose.test.yml") +@pytest.fixture(scope="session") +def docker_compose_project_name(): + """Use a consistent project name to avoid creating new networks each run.""" + return "reflector_test" + + +@pytest.fixture(scope="session", autouse=True) +def cleanup_docker_resources(): + """Clean up Docker test resources before and after test session.""" + + def cleanup(): + # Stop and remove any existing test containers + # This will also remove the reflector_test network if it exists + subprocess.run( + [ + "docker", + "compose", + "-p", + "reflector_test", + "down", + "-v", + "--remove-orphans", + ], + capture_output=True, + cwd=os.path.dirname(os.path.dirname(os.path.abspath(__file__))), + ) + # Clean up any unused networks (includes orphaned pytest networks) + # This is safe - only removes networks with no attached containers + subprocess.run(["docker", "network", "prune", "-f"], capture_output=True) + + # Clean before tests + cleanup() + + yield + + # Clean after tests + cleanup() + + @pytest.fixture(scope="session") def postgres_service(docker_ip, docker_services): """Ensure that PostgreSQL service is up and responsive.""" - port = docker_services.port_for("postgres_test", 5432) + try: + port = docker_services.port_for("postgres_test", 5432) + except Exception as e: + # If Docker services fail to start, clean up and retry + subprocess.run(["docker", "network", "prune", "-f"], capture_output=True) + subprocess.run( + ["docker", "compose", "-p", "reflector_test", "down", "-v"], + capture_output=True, + ) + raise pytest.skip(f"Docker services failed to start: {e}") def is_responsive(): try: