improve comment getfixturevalue, move test_scoped_fixture_teardown_order to testing/python/fixtures.py

This commit is contained in:
jakkdl 2024-03-03 13:22:23 +01:00
parent 3fc5c5530e
commit 007d24a6fa
3 changed files with 59 additions and 38 deletions

View File

@ -531,8 +531,11 @@ class FixtureRequest(abc.ABC):
:raises pytest.FixtureLookupError:
If the given fixture could not be found.
"""
# Note: This is called during setup for evaluating fixtures defined via
# function arguments as well.
# Note that in addition to the use case described in the docstring,
# getfixturevalue() is also called by pytest itself during item setup to
# evaluate the fixtures that are requested statically
# (using function parameters, autouse, etc).
fixturedef = self._get_active_fixturedef(argname)
assert fixturedef.cached_result is not None, (
f'The fixture value for "{argname}" is not available. '

View File

@ -4561,6 +4561,60 @@ def test_deduplicate_names() -> None:
assert items == ("a", "b", "c", "d", "g", "f", "e")
def test_scoped_fixture_teardown_order(pytester: Pytester) -> None:
"""
Make sure teardowns happen in reverse order of setup with scoped fixtures, when
a later test only depends on a subset of scoped fixtures.
Regression test for https://github.com/pytest-dev/pytest/issues/1489
"""
pytester.makepyfile(
"""
from typing import Generator
import pytest
last_executed = ""
@pytest.fixture(scope="module")
def fixture_1() -> Generator[None, None, None]:
global last_executed
assert last_executed == ""
last_executed = "autouse_setup"
yield
assert last_executed == "noautouse_teardown"
last_executed = "autouse_teardown"
@pytest.fixture(scope="module")
def fixture_2() -> Generator[None, None, None]:
global last_executed
assert last_executed == "autouse_setup"
last_executed = "noautouse_setup"
yield
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

View File

@ -1,36 +0,0 @@
from typing import Generator
import pytest
last_executed = ""
@pytest.fixture(scope="module")
def fixture_1() -> Generator[None, None, None]:
global last_executed
assert last_executed == ""
last_executed = "autouse_setup"
yield
assert last_executed == "noautouse_teardown"
last_executed = "autouse_teardown"
@pytest.fixture(scope="module")
def fixture_2() -> Generator[None, None, None]:
global last_executed
assert last_executed == "autouse_setup"
last_executed = "noautouse_setup"
yield
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:
pass