test_fixtures_request_different_scope.py
Overview
This file contains pytest fixtures and test cases designed to demonstrate and verify the behavior of pytest fixtures with different scopes, particularly focusing on how fixtures defined at different levels (module-level and class-level) interact and get executed. Specifically, it illustrates how pytest resolves fixture dependencies and the order in which fixtures are invoked when multiple fixtures with the same name but different scopes exist.
The tests in this file emphasize the interaction between module-level and class-level fixtures named `inner` and how they affect the shared `order` list. The `order` list is used to track the sequence of fixture invocations, which is then asserted in the tests to confirm the expected order and scope resolution behavior.
Detailed Explanation of Contents
Fixtures
order (module-level fixture)
@pytest.fixture
def order():
return []
Purpose: Provides a fresh, empty list for each test invocation to track the order in which fixtures are called.
Scope: Function scope (default).
Parameters: None.
Returns: An empty list (
[]).Usage: Passed to other fixtures and test functions to append strings representing the sequence of fixture calls.
outer (module-level fixture)
@pytest.fixture
def outer(order, inner):
order.append("outer")
Purpose: Depends on both
orderandinnerfixtures; appends"outer"to theorderlist afterinnerhas been resolved and executed.Scope: Function scope (default).
Parameters:
order: The list tracking fixture call order.inner: Another fixture (resolved either from module-level or class-level, depending on context).
Returns:
Noneexplicitly (fixture is used for side effects).Usage: Used in test cases to verify the combined execution order of
inner(which varies by test class) andouter.
Classes and Their Fixtures
TestOne
Class-level fixture
inner
@pytest.fixture
def inner(self, order):
order.append("one")
Purpose: Overrides the
innerfixture forTestOneclass tests; appends"one"to theorderlist.Scope: Function scope (default).
Parameters:
order: The list tracking fixture call order.
Returns:
Noneexplicitly.Usage: Ensures that within
TestOne, theinnerfixture appends"one"to the order rather than any module-levelinner.Test method
test_order
def test_order(self, order, outer):
assert order == ["one", "outer"]
Purpose: Validates that the
orderlist reflects the sequence of fixture calls, specifically thatinner(class-level) runs beforeouter.Parameters:
order: The list tracking fixture call order.outer: The outer fixture that depends oninner.
Returns: None (asserts correctness).
Behavior: Expects that the
orderlist contains"one"followed by"outer".
TestTwo
Class-level fixture
inner
@pytest.fixture
def inner(self, order):
order.append("two")
Purpose: Overrides the
innerfixture forTestTwoclass tests; appends"two"to theorderlist.Scope: Function scope (default).
Parameters:
order: The list tracking fixture call order.
Returns: None explicitly.
Usage: Ensures that within
TestTwo, theinnerfixture appends"two"to the order.Test method
test_order
def test_order(self, order, outer):
assert order == ["two", "outer"]
Purpose: Validates that the
orderlist reflects the sequence of fixture calls, with theinnerfixture fromTestTworunning beforeouter.Parameters:
order: The list tracking fixture call order.outer: The outer fixture that depends oninner.
Returns: None (asserts correctness).
Behavior: Expects that the
orderlist contains"two"followed by"outer".
Important Implementation Details and Behavior
The
innerfixture is defined twice at the class level, once in each test class (TestOneandTestTwo), effectively overriding any module-level fixture namedinner(note: there is no module-levelinnerfixture explicitly defined in this file, butouterdepends oninner, so pytest resolvesinnerdynamically).The
outerfixture is defined once at the module level and depends on theinnerfixture. Depending on which test class is running, pytest injects the appropriateinnerfixture (class-level) intoouter.The
orderlist tracks the sequence of calls to verify fixture invocation order.When the test runs, pytest first resolves
inner(class fixture), which appends either"one"or"two"to the list, thenouterappends"outer".This demonstrates pytest's fixture resolution order and scoping: class-level fixtures override module-level fixtures with the same name when used in class tests.
Interaction with Other Parts of the System
This file is a test module intended to be executed by the pytest testing framework.
It interacts with pytest's fixture mechanism, illustrating fixture scoping and dependency injection.
It does not interact directly with application logic but serves as a learning and verification tool for fixture behavior.
Other test modules or the application code can rely on similar fixture techniques for managing test setup and teardown.
It assumes pytest is installed and available in the test environment.
Usage Example
To run the tests and verify fixture order behavior, execute:
pytest test_fixtures_request_different_scope.py
Expected output is that both tests pass, confirming that:
In
TestOne,innerappends"one", thenouterappends"outer".In
TestTwo,innerappends"two", thenouterappends"outer".
Mermaid Class Diagram
classDiagram
class TestOne {
+inner(self, order)
+test_order(self, order, outer)
}
class TestTwo {
+inner(self, order)
+test_order(self, order, outer)
}
class Fixtures {
+order()
+outer(order, inner)
}
TestOne ..|> Fixtures : uses
TestTwo ..|> Fixtures : uses
Explanation:
Fixturesrepresents the module-level fixturesorderandouter.Both
TestOneandTestTwodefine their owninnerfixture and test methodtest_order.Both test classes use the module-level fixtures, demonstrating hierarchical fixture usage and override.
Summary
This file is a focused pytest test module demonstrating how pytest fixtures can be scoped and overridden at different levels (module and class) and how fixture dependencies are resolved. It uses an `order` list to track and assert the sequence of fixture calls, providing clarity on fixture invocation order and scope precedence. This is useful for developers needing to understand complex fixture interactions in pytest testing suites.