bluefox_test_setup()¶
The main setup function that wires all test infrastructure together.
Signature¶
def bluefox_test_setup(
base, # SQLAlchemy DeclarativeBase
binds: dict[str, str] | None = None, # {"analytics": "analytics.models:Base"}
src_root: str = "src", # where to discover tests/factories.py
postgres_image: str = "postgres:16-alpine",
redis_image: str = "redis:7-alpine",
app_factory: str | None = "app.main:create_app",
session_dependency: str | None = "app.deps:get_session",
) -> dict[str, Any]:
Returns a dict of pytest fixtures. Inject via globals().update(...) in your root conftest.py.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
base | DeclarativeBase | required | Your SQLAlchemy base class. Used for create_all(). |
binds | dict[str, str] \| None | None | Named additional databases. Keys become fixture names (db_<key>). Values are dotted paths to bind base classes. |
src_root | str | "src" | Root directory for factory auto-discovery. |
postgres_image | str | "postgres:16-alpine" | Docker image for the Postgres container. |
redis_image | str | "redis:7-alpine" | Docker image for the Redis container. |
app_factory | str \| None | "app.main:create_app" | Dotted path to your FastAPI app factory. Set to None to skip app/client fixtures. |
session_dependency | str \| None | "app.deps:get_session" | Dotted path to the FastAPI dependency that yields a session. Used for dependency override. |
Fixtures provided¶
| Fixture | Scope | Description |
|---|---|---|
infra | session | Starts Postgres + Redis containers, yields URLs |
safe_env | session, autouse | Overwrites env vars with container URLs, runs safety checks |
engine | session | Async engine for main DB, runs create_all() |
db | function | SAVEPOINT-wrapped async session, binds factories |
app | function | FastAPI app with test session injected via dependency override |
client | function | httpx AsyncClient wired to the app via ASGI transport |
bind_engines | session | Per-bind engines (only when binds is provided) |
db_<name> | function | Per-bind SAVEPOINT sessions (one for each key in binds) |
create_* | function | One per factory discovered in tests/factories.py files |
How app wiring works¶
The package imports your app factory and session dependency using the dotted paths:
# This is what happens internally — you don't write this
from app.main import create_app
from app.deps import get_session
application = create_app()
async def _override_session():
yield test_session
application.dependency_overrides[get_session] = _override_session
If your app doesn't follow this pattern, set app_factory=None and define your own app and client fixtures. See the custom app wiring guide.
Examples¶
Minimal setup¶
conftest.py
from bluefox_test import bluefox_test_setup
from app.models import Base
globals().update(bluefox_test_setup(base=Base))
With multiple databases¶
conftest.py
from bluefox_test import bluefox_test_setup
from app.models import Base
globals().update(
bluefox_test_setup(
base=Base,
binds={
"analytics": "analytics.models:AnalyticsBase",
},
)
)
Without app fixtures¶
conftest.py
from bluefox_test import bluefox_test_setup
from app.models import Base
globals().update(bluefox_test_setup(base=Base, app_factory=None))
This gives you db, engine, and factory fixtures, but no app or client.