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:

  1. Default to function scope
  2. Module scope only for sequential flows
  3. Never create data at session scope
  4. Match fixture scope to client scope

See also


Back to top

splent. Distributed by an LGPL license v3. Contact us: drorganvidez@us.es