SuperAPI AI Directory

testing

Testing & quality

View repository

Updated 10-16 17:28

About this skill

Python Testing

A collection of test-writing best practices for pytest. Designed for AI agents and LLMs to write readable, maintainable, and trustworthy tests.

Categories

Mocking [CRITICAL]

Mock external boundaries only, and keep mocks faithful to real interfaces.

Rule Description
mock-boundaries Mock external boundaries, not internal logic
mock-autospec Use autospec to keep mocks faithful to real signatures
mock-monkeypatch Use monkeypatch for env vars and attributes

Test Structure [HIGH]

Structure tests so failures are easy to diagnose.

Rule Description
struct-aaa-pattern Structure tests as Arrange-Act-Assert
struct-test-naming Name tests after the behavior they verify
struct-one-behavior Test one behavior per test
struct-no-logic Keep conditionals and loops out of tests

Fixtures [HIGH]

Share setup without hiding it.

Rule Description
fixture-scope Use the narrowest fixture scope that works
fixture-conftest Place fixtures in the nearest conftest.py
fixture-factory Use factory fixtures for varied test data

Parametrization [MEDIUM]

Eliminate duplicated tests without hiding cases.

Rule Description
param-parametrize Replace duplicated tests with parametrize
param-ids Give parametrized cases readable ids

Quick Reference

Structure Patterns

def test_expired_token_is_rejected() -> None:
    # Arrange
    token = make_token(expires_at=YESTERDAY)

    # Act
    result = validate(token)

    # Assert
    assert result.valid is False

Fixture Patterns

# Narrow scope by default
@pytest.fixture
def user() -> User:
    return User(name="alice", email="alice@example.com")

# Factory fixture for varied data
@pytest.fixture
def make_user() -> Callable[..., User]:
    def _make(name: str = "alice", active: bool = True) -> User:
        return User(name=name, email=f"{name}@example.com", active=active)
    return _make

Parametrize Patterns

@pytest.mark.parametrize(
    ("email", "valid"),
    [
        pytest.param("a@example.com", True, id="simple-address"),
        pytest.param("a@sub.example.com", True, id="subdomain"),
        pytest.param("no-at-sign", False, id="missing-at"),
        pytest.param("", False, id="empty-string"),
    ],
)
def test_email_validation(email: str, valid: bool) -> None:
    assert is_valid_email(email) is valid

Mocking Patterns

# Mock the external boundary with a faithful interface.
# `mocker` requires the pytest-mock plugin; with stdlib only,
# use unittest.mock.patch as a decorator or context manager.
def test_notifies_on_signup(mocker: MockerFixture) -> None:
    send = mocker.patch("app.signup.email_client.send", autospec=True)

    signup(email="alice@example.com")

    send.assert_called_once_with(to="alice@example.com", template="welcome")

# monkeypatch for environment variables
def test_reads_api_key(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setenv("API_KEY", "test-key")
    assert load_config().api_key == "test-key"

See Also