@@ -4219,6 +4219,68 @@ def test_func(my_fixture):
42194219 )
42204220
42214221
4222+ def test_fixture_post_finalizer_called_once (pytester : Pytester ) -> None :
4223+ """Test that pytest_fixture_post_finalizer is called only once per fixture teardown.
4224+
4225+ When a fixture depends on multiple parametrized fixtures and all their parameters
4226+ change at the same time, the dependent fixture should be torn down only once,
4227+ and pytest_fixture_post_finalizer should be called only once for it.
4228+ """
4229+ pytester .makeconftest (
4230+ """
4231+ import pytest
4232+
4233+ finalizer_calls = []
4234+
4235+ def pytest_fixture_post_finalizer(fixturedef, request):
4236+ finalizer_calls.append(fixturedef.argname)
4237+
4238+ @pytest.fixture(autouse=True)
4239+ def check_finalizer_calls(request):
4240+ yield
4241+ # After each test, verify no duplicate finalizer calls.
4242+ if finalizer_calls:
4243+ assert len(finalizer_calls) == len(set(finalizer_calls)), (
4244+ f"Duplicate finalizer calls detected: {finalizer_calls}"
4245+ )
4246+ finalizer_calls.clear()
4247+ """
4248+ )
4249+ pytester .makepyfile (
4250+ test_fixtures = """
4251+ import pytest
4252+
4253+ @pytest.fixture(scope="session")
4254+ def foo(request):
4255+ return request.param
4256+
4257+ @pytest.fixture(scope="session")
4258+ def bar(request):
4259+ return request.param
4260+
4261+ @pytest.fixture(scope="session")
4262+ def baz(foo, bar):
4263+ return f"{foo}-{bar}"
4264+
4265+ @pytest.mark.parametrize("foo,bar", [(1, 1)], indirect=True)
4266+ def test_first(foo, bar, baz):
4267+ assert foo == 1
4268+ assert bar == 1
4269+ assert baz == "1-1"
4270+
4271+ @pytest.mark.parametrize("foo,bar", [(2, 2)], indirect=True)
4272+ def test_second(foo, bar, baz):
4273+ assert foo == 2
4274+ assert bar == 2
4275+ assert baz == "2-2"
4276+ """
4277+ )
4278+ result = pytester .runpytest ("-v" )
4279+ # The test passes, which means no duplicate finalizer calls were detected
4280+ # by the check_finalizer_calls autouse fixture.
4281+ result .assert_outcomes (passed = 2 )
4282+
4283+
42224284class TestScopeOrdering :
42234285 """Class of tests that ensure fixtures are ordered based on their scopes (#2405)"""
42244286
0 commit comments