fixtures.py
Overview
The [fixtures.py](/projects/286/67499) file is a core part of the testing framework's fixture management system. It provides the infrastructure required to declare, discover, resolve, execute, cache, parametrize, and finalize fixtures. Fixtures are reusable test resources or setup/teardown logic that tests can request declaratively by name.
This file implements:
Fixture definition and registration: Using the @fixture decorator and related classes.
Fixture resolution and dependency injection: Resolving fixture dependencies transitively and enforcing scope rules.
Fixture lifecycle management: Executing fixture setup, caching results, and running finalizers for teardown.
Fixture parametrization: Supporting multiple parameter values per fixture, generating multiple test invocations.
Fixture information tracking: Computing and caching fixture usage info per test function.
Test item reordering: Grouping parametrized tests to minimize setup/teardown overhead.
Error handling for missing or invalid fixtures.
The system tightly integrates with the test collection, test execution, and configuration components of the broader pytest system.
Detailed Explanation of Classes and Functions
Type Aliases and Data Classes
FixtureValue– Generic type variable representing the returned value of a fixture function.FixtureFunction– Type variable for a callable fixture function._FixtureFunc– Union type for a fixture function returning a value or yielding a generator._FixtureCachedResult– Tuple representing cached fixture results or exceptions.@dataclass PseudoFixtureDef
Represents a pseudo fixture (e.g., the special built-inrequestfixture). Stores cached result and scope.
pytest_sessionstart(session: Session) -> None
Initializes the fixture manager for a pytest session.
Scope Helper Functions
get_scope_package(node, fixturedef) -> Optional[nodes.Node]
Finds the appropriate package-level scope node for a fixture.get_scope_node(node, scope) -> Optional[nodes.Node]
Returns the closest parent node matching a given scope (function, class, module, package, session).
Fixture Sorting Helpers
ParamArgKey: Data class representing a key for parametrized fixture parameters for sorting.get_param_argkeys(item, scope) -> Iterator[ParamArgKey]
Returns all parameter keys for a test item matching a given fixture scope.reorder_items(items) -> list[nodes.Item]
Reorders test items to group them by parametrized fixture parameters at higher scopes to minimize costly setup/teardown.reorder_items_atscope(...) -> OrderedSet[nodes.Item]
Recursive helper implementing sorting logic per scope.
FuncFixtureInfo
Holds static fixture-related information for a test function/item: requested fixture names, initial fixture names including autouse and usefixtures, transitive fixture closure, and mapping from fixture name to matching
FixtureDefs.prune_dependency_tree()
Prunes the transitive closure of fixtures based on direct parametrization to reduce unused fixtures.
FixtureRequest (Abstract Base Class)
Represents the context of a fixture request, e.g., the `request` object available inside fixtures and tests.
Attributes:
fixturename: Name of the fixture being requested (or None for the top-level request)._pyfuncitem: The test function item._arg2fixturedefs: Mapping fixture names to possibleFixtureDefs._fixture_defs: Cached resolved fixturedefs for names requested so far.param: Current param value if parametrized, else Any.
Properties:
_scope: Abstract property for scope of this request.scope: Scope string ("function", "class", etc).fixturenames: List of all active fixture names in this request.node: Abstract property for the underlying collection node.config: Pytest config object.function,cls,instance,module,path,keywords,session: Various contextual attributes based on scope.
Methods:
addfinalizer(finalizer): Register a finalizer callable.applymarker(marker): Apply a marker to the test invocation.raiseerror(msg): Raise aFixtureLookupError.getfixturevalue(argname): Dynamically retrieve and execute a fixture by name.Internal helpers to manage fixturedef retrieval and scope checking.
TopRequest(FixtureRequest)
Represents the top-level fixture request in a test function.
Scope is always function.
Responsible for filling the test function's fixture arguments.
Implements
nodeproperty returning the test function item.
SubRequest(FixtureRequest)
Represents a nested fixture request inside another fixture.
Manages scope, parameters, and the associated fixturedef.
Implements scope checks to prevent scope violations.
Provides access to the appropriate node for the scope.
Finalizers are added to the associated fixturedef.
FixtureLookupError(LookupError)
Raised when a requested fixture is missing or invalid.
Contains information about the fixture stack leading to the error.
Provides a rich terminal representation (
FixtureLookupErrorRepr) for user-friendly error messages.
call_fixture_func(fixturefunc, request, kwargs)
Calls the fixture function with resolved dependencies.
Supports generator fixtures (yield fixtures) by splitting setup and teardown code.
Registers teardown finalizers for yield fixtures.
_teardown_yield_fixture(fixturefunc, it)
Helper called to run the teardown part of a yield fixture by advancing the generator.
_eval_scope_callable(scope_callable, fixture_name, config)
Evaluates a user-provided callable to dynamically determine a fixture’s scope.
FixtureDef
Encapsulates a fixture definition.
Holds metadata: function, scope, parameters, IDs, location baseid.
Manages cached fixture results and finalizers.
Key methods:
execute(request): Executes the fixture function, managing caching, dependencies, and finalizers.finish(request): Runs all finalizers and clears cache.cache_key(request): Returns the cache key for this fixture instance.
Provides
scopeproperty to get string representation of scope.
resolve_fixture_function(fixturedef, request)
Returns the actual callable fixture function, bound to the test instance if applicable.
pytest_fixture_setup(fixturedef, request)
Core hook to setup and execute a fixture function.
Resolves dependencies and calls the fixture function.
Warns on async fixture usage without plugin support.
Caches results or exceptions.
FixtureFunctionMarker
Immutable data class representing the metadata of a fixture decorator.
Holds scope, params, autouse, ids, and optional name.
Callable to decorate a function and create a
FixtureFunctionDefinition.
FixtureFunctionDefinition
Wrapper around a fixture function supporting descriptor protocol.
Prevents direct calls, enforcing fixture usage via dependency injection.
Contains metadata and callable forwarding.
fixture(...)
The public decorator function used by users to define fixtures.
Supports parameters: scope, params, autouse, ids, name.
Returns either
FixtureFunctionMarkerorFixtureFunctionDefinitiondepending on usage.
Deprecated: yield_fixture
Deprecated wrapper for yield-based fixtures; redirects to
fixture.
Built-in Fixtures
pytestconfig: Session-scoped fixture providing access to the pytest Config object.
CLI and Config Integration
pytest_addoption(parser): Adds CLI options and ini configuration for fixture usage display.pytest_cmdline_main(config): Handles CLI options to show fixture information or per-test fixture usage.
Fixture Info Utilities
_get_direct_parametrize_args(node): Extracts direct parametrize argument names from a test node.deduplicate_names(*seqs): Removes duplicates from sequences of fixture names preserving order.
FixtureManager
Central manager for all fixture definitions and info.
Tracks registered fixtures (
_arg2fixturedefs), autouse fixtures, and usefixtures.Core methods:
getfixtureinfo(node, func, cls): Computes FuncFixtureInfo for a test item.pytest_plugin_registered(plugin, plugin_name): Registers fixtures from plugins and conftests.getfixturedefs(argname, node): Gets applicable fixtures for a node.parsefactories(node_or_obj, nodeid): Parses fixtures from a node or object, registers them.pytest_generate_tests(metafunc): Generates parametrized tests for parametrized fixtures.pytest_collection_modifyitems(items): Reorders items to optimize fixture setup.
Internal helpers to handle autouse and usefixtures names.
Fixtures Display Functions
show_fixtures_per_test(config): Displays fixtures used by each test._show_fixtures_per_test(config, session): Implements display logic.showfixtures(config): Displays all available fixtures._showfixtures_main(config, session): Implements detailed fixtures display.Helper function write_docstring for formatting fixture docstrings.
Important Implementation Details and Algorithms
Fixture Resolution and Caching
Fixtures are cached per scope and parameter combination. Theexecutemethod inFixtureDefchecks if the cached value matches the current request’s parameter. If not, it tears down the old fixture and sets up a new instance.Dependency Graph Traversal
Fixture dependencies are resolved recursively by callinggetfixturevalueon requested fixture names. This builds and caches a dependency graph of fixtures.Scope Enforcement
The system enforces that fixtures with wider scopes do not depend on narrower scoped fixtures to avoid invalid lifetime issues.Parametrized Fixture Sorting
Tests are reordered using a recursive algorithm (reorder_items_atscope) that groups tests by high-scope parameter keys (ParamArgKey) to minimize redundant fixture setup/teardown.Yield Fixtures Finalization
Yield-based fixtures use generator functions. Pytest runs setup code beforeyield, caches the yielded value, and registers a finalizer to resume the generator to run teardown code.Dynamic Fixture Requests
Therequest.getfixturevaluemethod allows fixtures and tests to dynamically request fixtures by name at runtime, expanding the static dependency graph.
Interaction with Other System Components
Test Collection (
nodes.py,python.py)
Fixtures are discovered during test collection. TheFixtureManagerqueries collected nodes and plugin objects to find fixture definitions.Test Execution (
runner.py)
Fixtures are resolved and executed before running test functions. The cached fixture values are injected as test function arguments.Configuration (
config/__init__.py)
Provides CLI options and ini settings affecting fixture visibility and usage (e.g.,usefixtures).Marking System (
mark/structures.py)
Fixtures interact with markers for parametrization and autouse behavior.Plugin System
Plugins can define fixtures which are registered via theFixtureManager.Terminal Output (
_pytest._io,_pytest._code)
Fixture errors and fixture listings use rich terminal representations for user feedback.
Usage Examples
Defining a Fixture
import pytest
@pytest.fixture(scope="module", params=[1, 2, 3])
def sample_data(request):
return request.param
Using a Fixture in Tests
def test_example(sample_data):
assert sample_data in [1, 2, 3]
Accessing Fixtures Dynamically
def test_dynamic(request):
value = request.getfixturevalue("sample_data")
assert value in [1, 2, 3]
Adding a Finalizer
@pytest.fixture
def resource(request):
res = acquire_resource()
def cleanup():
res.release()
request.addfinalizer(cleanup)
return res
Mermaid Diagram: Class Structure Overview
classDiagram
class FixtureManager {
+getfixtureinfo(node, func, cls)
+parsefactories(node_or_obj, nodeid)
+getfixturedefs(argname, node)
+pytest_generate_tests(metafunc)
+pytest_collection_modifyitems(items)
}
class FixtureDef {
+argname: str
+scope: str
+func: callable
+params: Sequence
+cached_result
+addfinalizer(finalizer)
+execute(request)
+finish(request)
}
class FixtureRequest {
+fixturename: Optional[str]
+param: Any
+getfixturevalue(argname)
+addfinalizer(finalizer)
+applymarker(marker)
}
class TopRequest {
+_scope: Scope
+_fillfixtures()
}
class SubRequest {
+_scope: Scope
+_parent_request: FixtureRequest
+param_index: int
}
class FixtureFunctionMarker {
+scope
+params
+autouse
+ids
+name
+__call__(function)
}
class FixtureFunctionDefinition {
+__call__(*args, **kwargs)
+__get__(instance, owner)
}
class FixtureLookupError {
+argname
+request
+fixturestack
+formatrepr()
}
FixtureManager "1" -- "*" FixtureDef : manages
FixtureDef "1" -- "*" "Callable" : wraps
FixtureRequest <|-- TopRequest
FixtureRequest <|-- SubRequest
FixtureFunctionMarker --> FixtureFunctionDefinition : creates
Summary
[fixtures.py](/projects/286/67499) is a comprehensive implementation of pytest’s fixture system, providing:
A robust system to declare, register, and manage fixtures with scoped lifetimes.
Support for parametrization creating multiple test instances from one fixture.
Recursive dependency resolution and caching of fixture results.
Lifecycle management that ensures setup and teardown happen at the right times.
Detailed error reporting and integration with pytest's test collection and execution phases.
Facilities to inspect and display fixture information to users for better debugging and understanding.
This file is foundational to pytest’s powerful fixture mechanism, enabling scalable, maintainable, and readable test suites.