Fixtures
Framework-provided fixtures, custom feature fixtures, scope rules, and patterns for creating test data.
Table of contents
Framework fixtures
Provided by splent_framework.fixtures.fixtures. Import them in your conftest.py:
from splent_framework.fixtures.fixtures import * # noqa: F401,F403
All fixtures share a _reset_db() helper that drops and recreates all tables with FK checks disabled.
test_app — session scope
Creates the Flask app once and initializes the schema.
@pytest.fixture(scope="session")
def test_app():
app = get_create_app_in_testing_mode()
with app.app_context():
_reset_db()
yield app
Use when: you need the app object for data fixtures or config access.
test_client — function scope
Flask test client with clean DB per test.
@pytest.fixture(scope="function")
def test_client(test_app):
with test_app.app_context():
_reset_db()
with test_app.test_client() as client:
yield client
Use when: most tests. Each starts with a clean slate.
test_client_module — module scope
Same but scoped to the file. Tests share DB state within the module.
Use when: tests form a sequence (create → update → delete).
Module-scoped tests are order-dependent. Default to function scope.
clean_database — function scope
Manually resets DB within a test. Combine with test_client_module for selective resets.
Custom fixtures
Add feature-specific fixtures after the framework import:
# splent_feature_auth/tests/conftest.py
from splent_framework.fixtures.fixtures import * # noqa: F401,F403
import pytest
from splent_io.splent_feature_auth.models import User
from splent_framework.db import db
@pytest.fixture(scope="function")
def auth_test_user(test_app):
with test_app.app_context():
user = User(email="user1@example.com", active=True)
user.set_password("1234")
db.session.add(user)
db.session.commit()
db.session.expunge(user)
return user
@pytest.fixture(scope="function")
def logged_in_client(test_client, auth_test_user):
test_client.post("/login", data={"email": "user1@example.com", "password": "1234"}, follow_redirects=True)
return test_client
Why db.session.expunge()
Detaches the object from the session so it can be returned to test functions without DetachedInstanceError. Always expunge objects you return from a fixture.
Composing fixtures
test_app (session)
└─ test_client (function) ─── resets DB
└─ auth_test_user (function) ─── creates user
└─ logged_in_client (function) ─── logs in
└─ sample_note (function) ─── creates note
pytest resolves the chain automatically.
Cross-feature data
Import upstream models directly:
from splent_io.splent_feature_auth.models import User
Works because feature:test sets PYTHONPATH to include all features.
Scope rules
| Scope | Resets DB? | Shared across | Use for |
|---|---|---|---|
function |
Per test | Nothing | Independent tests (default) |
module |
Per file | Tests in same file | Sequential flows |
session |
Once | All tests | App creation only |
Golden rules:
- Default to function scope
- Module scope only for sequential flows
- Never create data at session scope
- Match fixture scope to client scope
See also
- Test levels — where to use each fixture type
- Test environment — how the test DB is configured