Testing the Framework

splent_framework ships a set of pytest fixtures and helpers that handle app creation, database lifecycle, and test client setup for feature tests. Use them instead of writing your own to stay consistent with the framework conventions.

For a complete guide on how to set up and write tests in a feature — including fixtures, test users, scope selection, and examples at every level — see Feature testing.


Table of contents

  1. Fixtures
    1. test_app (session scope)
    2. test_client (function scope)
    3. test_client_module (module scope)
    4. clean_database (function scope)
  2. Test helpers
    1. Auth helpers
  3. Writing tests for a feature
    1. Running feature tests
  4. app_loader
  5. See also

Fixtures

File: splent_framework.fixtures.fixtures

Import all fixtures in your feature’s conftest.py:

# tests/conftest.py
from splent_framework.fixtures.fixtures import *  # noqa: F401,F403

All fixtures share a _reset_db() helper that disables MariaDB FK checks during drop, so cross-feature FK references don’t block table cleanup:

def _reset_db():
    db.session.remove()
    with db.engine.connect() as conn:
        conn.execute(text("SET FOREIGN_KEY_CHECKS=0"))
        db.metadata.drop_all(bind=conn)
        conn.execute(text("SET FOREIGN_KEY_CHECKS=1"))
        db.metadata.create_all(bind=conn)
        conn.commit()

test_app (session scope)

Creates the Flask application in testing mode once per test session, then drops and recreates all database tables.

@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 direct access to the Flask app object (e.g., to read app.config or push a context manually).

Scope: session — the app is created once and shared across all tests in the session.


test_client (function scope)

Provides a Flask test client with full database isolation per test. All tables are dropped and recreated before the test runs.

@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: you want a clean database for every single test function.

Example:

def test_login(test_client):
    response = test_client.post("/login", data={
        "email": "user@example.com",
        "password": "secret",
    })
    assert response.status_code == 302

test_client_module (module scope)

Same as test_client but scoped to the module. The database is reset once at the start of the module, not between individual tests.

@pytest.fixture(scope="module")
def test_client_module(test_app):
    with test_app.app_context():
        _reset_db()
        with test_app.test_client() as client:
            yield client

Use when: tests in the same module share state (e.g., a sequence of operations that build on each other) and resetting the database between each test would be too expensive or would break the intended flow.


clean_database (function scope)

Manually resets the database within a test. Does not provide a client — combine with test_client_module when you need selective resets within a module-scoped client.

@pytest.fixture(scope="function")
def clean_database(test_app):
    with test_app.app_context():
        _reset_db()
        yield

Use when: you have module-scoped state for most tests but one specific test must start with an empty database.


Test helpers

Auth helpers

File: splent_framework.helpers.test_helpers_auth

Utilities for authenticating test clients:

from splent_framework.helpers.test_helpers_auth import login, logout

def test_protected_route(test_client):
    login(test_client, "user@example.com", "secret")
    response = test_client.get("/profile")
    assert response.status_code == 200
    logout(test_client)

Writing tests for a feature

Each feature scaffold generated by feature:create includes a layered test structure:

tests/
├── conftest.py           # Shared fixtures (imports from splent_framework.fixtures)
├── unit/                 # Mocked dependencies, no DB, no HTTP — fast
│   └── test_services.py
├── integration/          # Real test DB, repositories, services
│   └── test_repositories.py
├── functional/           # Flask test_client, full HTTP request/response cycles
│   └── test_routes.py
├── e2e/                  # Selenium browser automation (real server required)
│   └── test_browser.py
└── load/                 # Locust performance tests
    └── locustfile.py

The conftest.py imports framework fixtures and defines feature-specific fixtures (test users, seed data, etc.). See Feature testing for a complete guide on fixture setup, scope selection, and examples at every level.

Running feature tests

From inside the SPLENT CLI container:

splent feature:test auth                     # Single feature, default levels
splent feature:test auth --unit              # Unit tests only
splent feature:test auth --integration -v    # Integration, verbose
splent feature:test                          # All features

app_loader

File: splent_framework.utils.app_loader

Used internally by the fixtures to import the active product’s create_app:

def get_create_app_in_testing_mode():
    app_name = os.getenv("SPLENT_APP")
    module = importlib.import_module(app_name)
    return module.create_app("testing")

This avoids any dependency on the CLI during test execution. Tests run purely in the Python environment with no Docker or CLI involvement.


See also


Back to top

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