Repository: pytest-dev/pytest
File: testing/python/fixtures.py (Python)

Code before:
            assert last_executed == "run_test"
            last_executed = "noautouse_teardown"


        def test_autouse_fixture_teardown_order(fixture_1: None, fixture_2: None) -> None:
            global last_executed
            assert last_executed == "noautouse_setup"
            last_executed = "run_test"


        def test_2(fixture_1: None) -> None:
            # this would previously queue an additional teardown of fixture_1,
            # despite fixture_1's value being cached, which caused fixture_1 to be
            # torn down before fixture_2 - violating the rule that teardowns should
            # happen in reverse order of setup.
            pass
        """
    )
    result = pytester.runpytest()
    assert result.ret == 0


def test_scope_fixture_caching_1(pytester: Pytester) -> None:
    """
    Make sure setup and finalization is only run once when using fixture
    multiple times. This might be a duplicate of another test."""
    pytester.makepyfile(
        """
        from __future__ import annotations

        from typing import Generator

        import pytest
        executed: list[str] = []
        @pytest.fixture(scope="class")
        def fixture_1() -> Generator[None, None, None]:
            executed.append("fix setup")
            yield
            executed.append("fix teardown")


        class TestFixtureCaching:
            def test_1(self, fixture_1: None) -> None:
                assert executed == ["fix setup"]

            def test_2(self, fixture_1: None) -> None:
                assert executed == ["fix setup"]


        def test_expected_setup_and_teardown() -> None:
            assert executed == ["fix setup", "fix teardown"]

Review comment (suggestion):
```suggestion
    """Make sure setup and finalization is only run once when using a fixture
    multiple times."""
```

Code after:
            ran_fixture = False

            def setup_method(self):
                assert not self.ran_setup_method
                self.ran_setup_method = True

            @pytest.fixture(autouse=True)
            def fixture(self):
                assert not self.ran_fixture
                self.ran_fixture = True

            def test_method(self):
                assert self.ran_setup_method
                assert self.ran_fixture

            @staticmethod
            def test_1(request):
                assert request.instance.ran_setup_method
                assert request.instance.ran_fixture

            @classmethod
            def test_2(cls, request):
                assert request.instance.ran_setup_method
                assert request.instance.ran_fixture
        """
    )
    result = pytester.runpytest()
    assert result.ret == ExitCode.OK
    result.assert_outcomes(passed=3)


def test_scoped_fixture_caching(pytester: Pytester) -> None:
    """Make sure setup and finalization is only run once when using scoped fixture
    multiple times."""
    pytester.makepyfile(
        """
        from __future__ import annotations

        from typing import Generator

        import pytest
        executed: list[str] = []
        @pytest.fixture(scope="class")
        def fixture_1() -> Generator[None, None, None]:
            executed.append("fix setup")
            yield
            executed.append("fix teardown")


        class TestFixtureCaching:
            def test_1(self, fixture_1: None) -> None: