The pytest Fixture Builder I Cannot Live Without

A four-stage tour of the fixture-builder pattern: a callable factory that mints test models with sensible defaults, layered overrides, deterministic IDs, and per-test isolation. The shape I paste into every conftest.py.

Python
Compiler
4 snippets
testing
unit-testing
code-template
utility
yunatorres

By @yunatorres

April 30, 2026

·

Updated May 18, 2026

687 views

2

4.3 (14)

from __future__ import annotations
import itertools
from typing import Any

_id_counter = itertools.count(1)


def make_user(**overrides: Any) -> dict:
    base = {
        'id': next(_id_counter),
        'email': '[email protected]',
        'name': 'Test User',
        'role': 'member',
        'verified': True,
    }
    base.update(overrides)
    return base


if __name__ == '__main__':
    print(make_user())
    print(make_user(name='Ada', role='admin'))
    print(make_user(email='[email protected]'))

The smallest version of the pattern is a function that returns a fresh dict every call, with sensible defaults that only matter when the test does not care about them. The id counter is module-level so two calls in the same test produce different ids without anyone having to remember to pass them. I have seen plenty of test suites use class-based factories from factory_boy for the same job; for unit tests I prefer the plain function because there is no metaclass, no Meta, and no debugger surprise. When the override is just name='Ada', you read the test and know exactly what is being exercised.