Test levels

How to write tests at each level (unit, integration, functional, and e2e), with real examples from the codebase.

Table of contents

Unit tests

Mock all external dependencies. No database, no Flask app, no HTTP. Fastest tests.

# splent_feature_auth/tests/unit/test_services.py
from unittest.mock import MagicMock, patch

@patch("splent_io.splent_feature_auth.services.login_user")
def test_authenticate_valid_user(mock_login_user):
    mock_user = MagicMock()
    mock_user.check_password.return_value = True

    repo = MagicMock()
    repo.get_by_email.return_value = mock_user

    service = AuthenticationService(user_repository=repo)
    result = service.login("user@example.com", "1234")

    assert result is True
    mock_login_user.assert_called_once_with(mock_user, remember=True)

Key points. No fixtures needed, mock repositories, patch external calls, test logic in isolation.


Integration tests

Real test database. Verify repositories, queries, and model relationships.

# splent_feature_profile/tests/integration/test_repositories.py
def test_create_and_retrieve_profile(test_client):
    with test_client.application.app_context():
        user = User(email="integration@test.com", active=True)
        user.set_password("pass123")
        db.session.add(user)
        db.session.commit()

        profile = UserProfile(user_id=user.id, name="Test", surname="User")
        db.session.add(profile)
        db.session.commit()

        service = UserProfileService()
        found = service.get_by_user_id(user.id)

        assert found is not None
        assert found.name == "Test"

Key points. Use test_client (clean DB per test), wrap in app context, test real queries.


Functional tests

HTTP endpoints through Flask’s test client. Full stack active.

# splent_feature_auth/tests/functional/test_login_flow.py
def test_login_success(test_client, auth_test_user):
    response = test_client.post(
        "/login",
        data={"email": "user1@example.com", "password": "1234"},
        follow_redirects=True,
    )
    assert response.status_code == 200
    assert b"Invalid credentials" not in response.data

def test_notes_requires_login(test_client):
    response = test_client.get("/notes")
    assert response.status_code == 302
    assert "login" in response.headers.get("Location", "").lower()

Key points. Use test_client or logged_in_client, assert on status codes, response data, redirects.


E2E tests

Real browser via Selenium. Slow, requires running server.

# splent_feature_notes/tests/e2e/test_browser.py
from splent_framework.environment.host import get_host_for_selenium_testing
from splent_framework.selenium.common import initialize_driver, close_driver

@pytest.fixture()
def browser():
    driver = initialize_driver()
    yield driver
    close_driver(driver)

def test_index_page_loads(browser):
    host = get_host_for_selenium_testing()
    browser.get(f"{host}/notes")
    assert "notes" in browser.page_source.lower()

Run with splent feature:test --e2e.

initialize_driver() launches a local Chrome by default (Firefox via SELENIUM_BROWSER or the browser argument). When SELENIUM_GRID_URL is set it attaches to a Selenium Grid instead, and get_host_for_selenium_testing() returns SELENIUM_TARGET_URL when set. This is required with a grid, because the browser container resolves the URL and its localhost is not the application. See E2E (Selenium) for details.


Test helpers

Auth helpers

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/edit")
    assert response.status_code == 200
    logout(test_client)

Extending test_client per file

Override test_client locally to seed file-specific data.

@pytest.fixture(scope="function")
def test_client(test_client):
    with test_client.application.app_context():
        admin = User(email="admin@example.com", active=True)
        admin.set_password("admin1234")
        db.session.add(admin)
        db.session.commit()
    yield test_client

See also


Back to top

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