diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 409701cc..b22b613a 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -115,7 +115,7 @@ jobs: - name: Unit tests (local) if: matrix.backend == 'local' - run: pytest -m "not mongo and not sql and not redis and not s3" --cov=cachier --cov-report=term --cov-report=xml:cov.xml + run: pytest -m "not mongo and not sql and not redis and not s3" -n auto --cov=cachier --cov-report=term --cov-report=xml:cov.xml - name: Setup docker (missing on MacOS) if: runner.os == 'macOS' && matrix.backend == 'mongodb' @@ -148,7 +148,7 @@ jobs: - name: Unit tests (DB) if: matrix.backend == 'mongodb' - run: pytest -m "mongo" --cov=cachier --cov-report=term --cov-report=xml:cov.xml + run: pytest -m "mongo" -n auto --cov=cachier --cov-report=term --cov-report=xml:cov.xml - name: Speed eval run: python tests/speed_eval.py @@ -169,7 +169,7 @@ jobs: if: matrix.backend == 'postgres' env: SQLALCHEMY_DATABASE_URL: postgresql+psycopg://testuser:testpass@localhost:5432/testdb - run: pytest -m sql --cov=cachier --cov-report=term --cov-report=xml:cov.xml + run: pytest -m sql -n auto --cov=cachier --cov-report=term --cov-report=xml:cov.xml - name: Start Redis in docker if: matrix.backend == 'redis' @@ -183,11 +183,11 @@ jobs: - name: Unit tests (Redis) if: matrix.backend == 'redis' - run: pytest -m redis --cov=cachier --cov-report=term --cov-report=xml:cov.xml + run: pytest -m redis -n auto --cov=cachier --cov-report=term --cov-report=xml:cov.xml - name: Unit tests (S3) if: matrix.backend == 's3' - run: pytest -m s3 --cov=cachier --cov-report=term --cov-report=xml:cov.xml + run: pytest -m s3 -n auto --cov=cachier --cov-report=term --cov-report=xml:cov.xml - name: Upload coverage to Codecov (non PRs) continue-on-error: true diff --git a/tests/README.md b/tests/README.md index acb8214f..de92da27 100644 --- a/tests/README.md +++ b/tests/README.md @@ -339,24 +339,26 @@ The CI pipeline runs a matrix job per backend. Each backend uses the commands be ```bash # Local backends (memory, pickle, and other non-external tests) -pytest -m "not mongo and not sql and not redis and not s3" +pytest -m "not mongo and not sql and not redis and not s3" -n auto # MongoDB backend -pytest -m mongo +pytest -m mongo -n auto # PostgreSQL/SQL backend -pytest -m sql +pytest -m sql -n auto # Redis backend -pytest -m redis +pytest -m redis -n auto # S3 backend -pytest -m s3 +pytest -m s3 -n auto ``` -Note: local tests do not use `pytest-xdist` (`-n`) in CI. External backends -(MongoDB, PostgreSQL, Redis, S3) each run in their own isolated matrix job with -the corresponding Docker service started beforehand. +All backends use `pytest-xdist` (`-n auto`) in CI for parallel test execution. +Each backend runs in its own isolated matrix job with the corresponding Docker +service started beforehand. Per-worker isolation is handled automatically by +the fixtures in `conftest.py` (separate cache directories for pickle/maxage +tests, separate PostgreSQL schemas for SQL tests). ### Environment Variables diff --git a/tests/conftest.py b/tests/conftest.py index 57d5dba0..9f0d47f1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -55,16 +55,7 @@ def inject_worker_schema_for_sql_tests(monkeypatch, request): # Rebuild the URL with updated query parameters new_query = urlencode(query_params, doseq=True) - new_url = urlunparse( - ( - parsed.scheme, - parsed.netloc, - parsed.path, - parsed.params, - new_query, - parsed.fragment - ) - ) + new_url = urlunparse((parsed.scheme, parsed.netloc, parsed.path, parsed.params, new_query, parsed.fragment)) # Override both the environment variable and the module constant monkeypatch.setenv("SQLALCHEMY_DATABASE_URL", new_url) @@ -155,14 +146,7 @@ def cleanup_test_schemas(request): # Rebuild clean URL clean_query = urlencode(query_params, doseq=True) if query_params else "" clean_url = urlunparse( - ( - parsed.scheme, - parsed.netloc, - parsed.path, - parsed.params, - clean_query, - parsed.fragment - ) + (parsed.scheme, parsed.netloc, parsed.path, parsed.params, clean_query, parsed.fragment) ) engine = create_engine(clean_url)