Fixtures Reference

This page documents fixtures and fixture recommendations for pytest-test-categories.

Plugin-Provided Fixtures

pytest-test-categories does not currently provide any custom fixtures. The plugin operates through pytest hooks rather than fixtures, which allows it to work seamlessly with your existing test infrastructure.


Fixture Scope Best Practices

Scope Selection Guide

Small Tests:  function > class > module
Medium Tests: function ~ class ~ module > session
Large Tests:  Depends on resource cost and reuse

Anti-Patterns to Avoid

  1. Session fixtures in small tests:

    # BAD: Breaks test isolation
    @pytest.fixture(scope="session")
    def shared_state():
        return {"counter": 0}
    
    @pytest.mark.small
    def test_one(shared_state):
        shared_state["counter"] += 1  # Modifies shared state!
    
  2. Network fixtures in small tests:

    # BAD: Network is blocked in small tests
    @pytest.fixture
    def api_response():
        return requests.get("https://api.example.com/data")
    
    @pytest.mark.small
    def test_process_data(api_response):  # Will fail!
        pass
    
  3. Real database in small tests:

    # BAD: Database is blocked in small tests
    @pytest.fixture
    def db_session():
        engine = create_engine("sqlite:///test.db")
        Session = sessionmaker(bind=engine)
        return Session()
    
    @pytest.mark.small
    def test_query(db_session):  # Will fail!
        pass
    

Fixture Patterns by Use Case

Test Doubles for Small Tests

import pytest

@pytest.fixture
def fake_repository():
    """In-memory repository for small tests."""
    class FakeRepository:
        def __init__(self):
            self._data = {}

        def save(self, id, entity):
            self._data[id] = entity

        def get(self, id):
            return self._data.get(id)

    return FakeRepository()

@pytest.mark.small
def test_service_saves_entity(fake_repository):
    service = EntityService(repository=fake_repository)
    service.create(id="123", name="Test")
    assert fake_repository.get("123")["name"] == "Test"

Temporary Files for Medium Tests

import pytest

@pytest.fixture
def config_file(tmp_path):
    """Create a temporary config file."""
    config = tmp_path / "config.yaml"
    config.write_text("debug: true\nlog_level: INFO")
    return config

@pytest.mark.medium
def test_load_configuration(config_file):
    config = load_config(config_file)
    assert config.debug is True

Database Transactions for Medium Tests

import pytest

@pytest.fixture
def db_transaction(test_database):
    """Database transaction that rolls back after each test."""
    connection = test_database.connect()
    transaction = connection.begin()
    yield connection
    transaction.rollback()
    connection.close()

@pytest.mark.medium
def test_insert_user(db_transaction):
    db_transaction.execute("INSERT INTO users (name) VALUES ('Test')")
    result = db_transaction.execute("SELECT name FROM users").fetchone()
    assert result[0] == "Test"
    # Transaction is rolled back automatically

Compatibility with pytest Fixtures

pytest-test-categories is fully compatible with all standard pytest fixtures and popular fixture-providing plugins:

Plugin

Compatibility

Notes

pytest-mock

Full

Recommended for small tests

pytest-asyncio

Full

Use appropriate markers

pytest-django

Full

Consider test size for DB tests

pytest-flask

Full

Consider test size for request tests

pytest-factoryboy

Full

Great for test data generation

pytest-lazy-fixture

Full

Works with size markers

pytest-xdist

Full

Parallel execution supported


Source Code References

While pytest-test-categories doesn’t provide fixtures directly, these modules handle fixture-related interactions:

Component

Location

Filesystem blocker

adapters/filesystem.py