We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Testing with pytest and Hypothesis step 4 of 19
Work Out Fixture Setup and Teardown Order
When a test asks for fixtures, pytest sets up each fixture's dependencies
before the fixture itself. After the test, it tears them down in reverse
order, so each fixture can still use its dependencies while it cleans up.
If worker needs pool and pool needs db, pytest sets up db, pool
and worker, then tears down worker, pool and db.
The grader cannot run pytest, so here you write that planning step
yourself. Your planner sees only fixture names and what each one needs. It
ignores scope and autouse.
resolve_fixture_order({"worker": ["pool"], "pool": ["db"]}, ["worker"])
# ["db", "pool", "worker"]
teardown_order(["db", "pool", "worker"])
# ["worker", "pool", "db"]
What to write
def resolve_fixture_order(
deps: Mapping[str, Sequence[str]], requested: Sequence[str]
) -> list[str]
def teardown_order(setup: Sequence[str]) -> list[str]
deps maps each fixture name to the names it needs. requested lists the
fixtures the test asks for. resolve_fixture_order returns the setup order
for those fixtures and everything they need, directly or through other
fixtures.
- Put each name in the result once, after all of its dependencies.
- A name is ready when all of its dependencies are already in the result. When several names are ready, take the smallest by Python's normal string comparison. Then work out again which names are ready.
- Do not change
depsorrequested.
teardown_order returns a new list with setup in reverse order. Keep
every entry, including any repeats in setup.
The alphabetical tie-break gives the tests one right answer to check. pytest does not use it.
Edge cases
- A name that appears twice in
requestedor in a dependency list still appears once in the result. - A name that is not a key in
depshas no dependencies. Real pytest reports an unknown fixture as an error. Here it is a fixture with nothing to wait for. - Leave out fixtures that the requested ones do not need, even if they form a cycle.
- An empty
requestedreturns[].
Cycles
A cycle is a loop of dependencies, such as a needing b and b needing
a. If some names remain but none is ready, raise FixtureCycleError with
this message:
fixture cycle: <every unresolved name, sorted, joined with ", ">
Include every name still waiting, not only the names in the loop. With
deps={"a": ["b"], "b": ["a"], "client": ["a"]} and requested=["client"],
the message is fixture cycle: a, b, client. client is outside the loop,
but it waits for a, so it never becomes ready either. A fixture that needs
itself is also a cycle.
What the driver reports
Keep solve as it is. On success it returns your setup and teardown
lists and an empty error string. If your code raises FixtureCycleError,
solve returns empty lists and puts the message in error. Names you
ordered before you found the cycle do not appear.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.