Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c78734c
Initial
Anton3 Jan 11, 2026
ba0ba86
Always fixture finish in teardown phase
Anton3 Jan 12, 2026
643afdf
Fix current_item_index
Anton3 Jan 12, 2026
1553d3f
Use nextitem to teardown stale fixtures
Anton3 Jan 12, 2026
917ff33
Fix exception handling
Anton3 Jan 12, 2026
455bdbb
Rewrite everything, add more tests
Anton3 Jan 15, 2026
e7c31fa
Add changelogs
Anton3 Jan 15, 2026
e9df3c1
Fix coverage
Anton3 Jan 15, 2026
5aef1d5
Fix changelogs
Anton3 Jan 15, 2026
54a3a35
Remove fixture finalizers as they become stale
Anton3 Jan 15, 2026
35eb82b
Fix typing
Anton3 Jan 15, 2026
2151943
Fix docs
Anton3 Jan 15, 2026
3e156b3
Expand changelog entries
Anton3 Jan 15, 2026
7f11150
Fix coverage
Anton3 Jan 15, 2026
3b69c2b
Catch TEST_OUTCOME, fix _finish_if_param_changed
Anton3 Jan 18, 2026
07a0a0c
Fix coverage
Anton3 Jan 18, 2026
25f5820
Merge branch 'main' into param-fixtures-deps
Anton3 Jan 18, 2026
60f4286
Use TypeAlias
Anton3 Jan 18, 2026
d88ccd9
Move finalizers management to SetupState
Anton3 Jan 19, 2026
4301de7
Minor diff cleanups
Anton3 Jan 19, 2026
dfcff79
Use double quotes in changelog's snippet
Anton3 Jan 19, 2026
a4b6489
Restart flaky test_timeout_and_exit
Anton3 Jan 19, 2026
e29ac16
Add FinalizerHandle class
Anton3 Jan 24, 2026
e4e6d53
Spelling
Anton3 Jan 24, 2026
95a8e33
Add __slots__ to FinalizerHandle
Anton3 Jan 24, 2026
4ec2452
Fix a comment on test_override_fixture_with_new_parametrized_fixture
Anton3 Feb 16, 2026
a7452e8
2043 is not fixed
Anton3 Feb 16, 2026
89342ab
Fix issues from initial review by bluetech
Anton3 Mar 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/14103.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixtures are now rebuilt when param changes for a fixture they depend on, if the dependency is via :func:`request.getfixturevalue() <pytest.FixtureRequest.getfixturevalue>`.
1 change: 1 addition & 0 deletions changelog/14114.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
An exception from :hook:`pytest_fixture_post_finalizer` no longer prevents fixtures from being torn down, causing additional errors in the following tests.
3 changes: 3 additions & 0 deletions changelog/4871.improvement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Garbage finalizers for fixture teardown are no longer accumulated in nodes and fixtures.

:func:`Node.addfinalizer <_pytest.nodes.Node.addfinalizer>` and :func:`request.addfinalizer() <pytest.FixtureRequest.addfinalizer>` now return a handle that allows to remove the finalizer.
1 change: 1 addition & 0 deletions changelog/5848.improvement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:hook:`pytest_fixture_post_finalizer` is no longer called extra times for the same fixture teardown.
63 changes: 63 additions & 0 deletions changelog/9287.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
Teardown of parametrized fixtures now happens in the teardown stage of the test before the parameter changes.

Previously teardown would happen in the setup stage of the test where the parameter changes.

If a test forces teardown of a parametrized fixture, e.g. using :func:`request.getfixturevalue() <pytest.FixtureRequest.getfixturevalue>`, it instead fails. An example of such test:

.. code-block:: pytest

# conftest.py
import pytest

@pytest.hookimpl(wrapper=True, tryfirst=True)
def pytest_collection_modifyitems(items):
# Disable built-in test reordering.
original_items = items[:]
yield
items[:] = original_items

# test_invalid.py
import pytest

@pytest.fixture(scope="session")
def foo(request):
return getattr(request, "param", "default")

@pytest.mark.parametrize("foo", [1], indirect=True)
def test_a(foo):
assert foo == 1

def test_b(request):
request.getfixturevalue("foo")

@pytest.mark.parametrize("foo", [1], indirect=True)
def test_c(foo):
assert foo == 1

This produces the following error:

.. code-block:: console
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also show the explanation part?

This could happen because the current test requested the previously parametrized fixture dynamically via 'getfixturevalue' and did not provide a parameter for the fixture.
Either provide a parameter for the fixture, or make fixture 'foo' statically reachable from the current test, e.g. by adding it as an argument to the test function.


Parameter for the requested fixture changed unexpectedly in test:
test_invalid.py::test_b
Requested fixture 'foo' defined in:
test_invalid.py:4

Previous parameter value: 1
New parameter value: None

This could happen because the current test requested the previously parametrized
fixture dynamically via 'getfixturevalue' and did not provide a parameter for the
fixture.
Either provide a parameter for the fixture, or make fixture 'foo' statically
reachable from the current test, e.g. by adding it as an argument to the test
function.

Indeed, the following change to ``test_b`` fixes the issue:

.. code-block:: pytest

def test_b(request, foo):
# This is now a little unnecessary as written, but imagine that this dynamic
# fixture loading happens inside another fixture or inside an utility function.
request.getfixturevalue("foo")
7 changes: 7 additions & 0 deletions doc/en/reference/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,13 @@ ExitCode
:members:


FinalizerHandle
~~~~~~~~~~~~~~~

.. autoclass:: pytest.FinalizerHandle()
:members:


FixtureDef
~~~~~~~~~~

Expand Down
Loading