Fixtures

Table of contents

Introduction

The framework’s fixtures build the app and reset the database. Your feature adds its own on top, for its test data. Import the framework’s in your conftest.py.

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

Using the framework’s fixtures

test_client (function scope)

A Flask test client with a clean database for every test. Use it for most tests.

def test_the_index_loads(test_client):
    assert test_client.get("/notes/").status_code == 200

test_app (session scope)

The product’s app, built once with its testing configuration. Use it when a data fixture needs the app, or a test needs its config.

The test app keeps its files in a temporary store, removed when the test process ends, never where the product keeps them. PROTECTED_UPLOADS_DIR, UPLOADS_DIR, the instance folder and the static uploads folder all point there. To give a test a folder of its own, set the variable.

def test_a_private_file(test_client, monkeypatch, tmp_path):
    monkeypatch.setenv("PROTECTED_UPLOADS_DIR", str(tmp_path))
    ...

The other fixtures

  • test_client_module shares one database across a file, for tests that form a sequence. They depend on their order, so default to function scope.
  • clean_database resets the database inside a test, where you choose.
  • no_access_policies runs a test with no access policies registered, to test your feature’s own role gate.

Every reset drops every table of the test database and creates the app’s, so no table keeps rows from another product’s tests. splent_migrations stays.


Writing your own fixtures

# splent_feature_notes/tests/conftest.py
from splent_framework.fixtures.fixtures import *  # noqa: F401,F403
import pytest
from splent_io.splent_feature_notes.models import Notes
from splent_framework.db import db

@pytest.fixture(scope="function")
def sample_note(test_app):
    with test_app.app_context():
        note = Notes(title="First note", content="Hello", published=True)
        db.session.add(note)
        db.session.commit()
        db.session.expunge(note)
        return note

@pytest.fixture(scope="function")
def note_page(test_client, sample_note):
    return test_client.get(f"/notes/{sample_note.id}", follow_redirects=True)

db.session.expunge() detaches the object, so a test can use it without DetachedInstanceError. Expunge every object a fixture returns. pytest resolves the chain, from test_app through test_client and sample_note to note_page.

Using another feature’s models

from splent_io.splent_feature_notes.models import Notes

The tests of reports, which requires notes, import its models. feature:test puts every feature your product declares on PYTHONPATH, at the version it pins. See Which copy is tested.


Choosing a scope

Scope Resets the database Use for
function Per test Independent tests, the default
module Per file Sequential flows
session Once Building the app only

Never create data at session scope, and match a fixture’s scope to its client’s.


See also


Back to top

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