Modern QA2026Shared Fixtures (conftest.py)
Log inJoin
14 / 18 · Book 14 · Exercises← prev⊞ allnext →Get the book →

1.14Shared Fixtures (conftest.py)

The conftest.py file is the heart of your pytest API test suite. It contains fixtures that provide authenticated sessions, base URLs, and test data factories.

import os
import pytest
import requests


@pytest.fixture(scope="session")
def base_url():
    """Base URL for the API under test. Defaults to localhost."""
    return os.environ.get("API_BASE_URL", "http://localhost:3000/api/v1")


@pytest.fixture(scope="session")
def auth_headers(base_url):
    """Authenticate once per test session and return headers."""
    r = requests.post(f"{base_url}/auth/login", json={
        "email": "test@example.com",
        "password": "testpass123"
    })
    assert r.status_code == 200, f"Auth failed: {r.text}"
    token = r.json()["access_token"]
    return {"Authorization": f"Bearer {token}"}


@pytest.fixture
def api(base_url, auth_headers):
    """Pre-configured API session with authentication."""
    session = requests.Session()
    session.headers.update(auth_headers)
    session.headers.update({"Content-Type": "application/json"})

    # Store base_url on session for convenience
    session._base_url = base_url
    original_request = session.request

    def patched_request(method, url, **kwargs):
        if url.startswith("/"):
            url = f"{base_url}{url}"
        return original_request(method, url, **kwargs)

    session.request = patched_request
    return session


@pytest.fixture
def create_user(api):
    """Factory fixture for creating test users with automatic cleanup."""
    created_ids = []

    def _create(name="Test User", email=None, role="viewer"):
        import uuid
        email = email or f"test-{uuid.uuid4().hex[:8]}@test.com"
        r = api.post("/users", json={
            "name": name, "email": email, "role": role
        })
        assert r.status_code == 201
        user = r.json()
        created_ids.append(user["id"])
        return user

    yield _create

    # Cleanup: delete all created users after the test
    for uid in created_ids:
        api.delete(f"/users/{uid}")

PRO TIP: The factory fixture pattern (create_user) is one of the most important patterns in API testing. It creates test data on demand and automatically cleans up after the test completes, preventing test data accumulation that can cause flaky tests.