Steven's Knowledge

Testing

Testing Python with pytest -- fixtures, parametrization, async tests, mocking external services, and shared conftest fixtures

Testing

pytest is the de facto standard for testing Python. Its fixture system provides clean dependency injection, parametrization gives you table-driven tests, and the ecosystem handles async and mocking with minimal ceremony.

Testing with pytest

import pytest
from unittest.mock import AsyncMock, patch

# Fixtures for dependency injection
@pytest.fixture
def db_session():
    session = create_test_session()
    yield session
    session.rollback()

# Parametrized tests (like Go's table-driven tests)
@pytest.mark.parametrize("input,expected", [
    ("$100.00", 10000),
    ("$0.50", 50),
    ("-$25.00", -2500),
])
def test_parse_amount(input: str, expected: int):
    assert parse_amount(input) == expected

# Async test
@pytest.mark.asyncio
async def test_fetch_user(db_session):
    user = await create_user(db_session, name="Alice")
    fetched = await get_user(db_session, user.id)
    assert fetched.name == "Alice"

# Mocking external services
async def test_payment_processing():
    with patch("app.services.stripe_client") as mock_stripe:
        mock_stripe.charge = AsyncMock(return_value={"id": "ch_123"})
        result = await process_payment(amount=1000, currency="nzd")
        assert result.stripe_id == "ch_123"
        mock_stripe.charge.assert_called_once()

# conftest.py -- shared fixtures across test modules
@pytest.fixture(scope="session")
def app():
    return create_app(testing=True)

@pytest.fixture(autouse=True)
def reset_db(db_session):
    yield
    db_session.rollback()

On this page