Skip to content

Commit

Permalink
Merge pull request #8323 from bluetech/setupstate-refactor-3
Browse files Browse the repository at this point in the history
runner: a few more tweaks to SetupState
  • Loading branch information
bluetech authored Feb 8, 2021
2 parents f85427b + 5822888 commit 1003bea
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/_pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ def _fill_fixtures_impl(function: "Function") -> None:
fi = fm.getfixtureinfo(function.parent, function.obj, None)
function._fixtureinfo = fi
request = function._request = FixtureRequest(function, _ispytest=True)
fm.session._setupstate.prepare(function)
fm.session._setupstate.setup(function)
request._fillfixtures()
# Prune out funcargs for jstests.
newfuncargs = {}
Expand Down
6 changes: 3 additions & 3 deletions src/_pytest/hookspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,9 +509,9 @@ def pytest_runtest_teardown(item: "Item", nextitem: Optional["Item"]) -> None:
:param nextitem:
The scheduled-to-be-next test item (None if no further test item is
scheduled). This argument can be used to perform exact teardowns,
i.e. calling just enough finalizers so that nextitem only needs to
call setup-functions.
scheduled). This argument is used to perform exact teardowns, i.e.
calling just enough finalizers so that nextitem only needs to call
setup functions.
"""


Expand Down
29 changes: 17 additions & 12 deletions src/_pytest/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ def runtestprotocol(
) -> List[TestReport]:
hasrequest = hasattr(item, "_request")
if hasrequest and not item._request: # type: ignore[attr-defined]
# This only happens if the item is re-run, as is done by
# pytest-rerunfailures.
item._initrequest() # type: ignore[attr-defined]
rep = call_and_report(item, "setup", log)
reports = [rep]
Expand Down Expand Up @@ -151,7 +153,7 @@ def show_test_item(item: Item) -> None:

def pytest_runtest_setup(item: Item) -> None:
_update_current_test_var(item, "setup")
item.session._setupstate.prepare(item)
item.session._setupstate.setup(item)


def pytest_runtest_call(item: Item) -> None:
Expand Down Expand Up @@ -417,7 +419,7 @@ class SetupState:
[]
During the setup phase of item1, prepare(item1) is called. What it does
During the setup phase of item1, setup(item1) is called. What it does
is:
push session to stack, run session.setup()
Expand All @@ -441,7 +443,7 @@ class SetupState:
[session]
During the setup phase of item2, prepare(item2) is called. What it does
During the setup phase of item2, setup(item2) is called. What it does
is:
push mod2 to stack, run mod2.setup()
Expand Down Expand Up @@ -477,23 +479,26 @@ def __init__(self) -> None:
],
] = {}

def prepare(self, item: Item) -> None:
def setup(self, item: Item) -> None:
"""Setup objects along the collector chain to the item."""
needed_collectors = item.listchain()

# If a collector fails its setup, fail its entire subtree of items.
# The setup is not retried for each item - the same exception is used.
for col, (finalizers, prepare_exc) in self.stack.items():
if prepare_exc:
raise prepare_exc
for col, (finalizers, exc) in self.stack.items():
assert col in needed_collectors, "previous item was not torn down properly"
if exc:
raise exc

needed_collectors = item.listchain()
for col in needed_collectors[len(self.stack) :]:
assert col not in self.stack
# Push onto the stack.
self.stack[col] = ([col.teardown], None)
try:
col.setup()
except TEST_OUTCOME as e:
self.stack[col] = (self.stack[col][0], e)
raise e
except TEST_OUTCOME as exc:
self.stack[col] = (self.stack[col][0], exc)
raise exc

def addfinalizer(self, finalizer: Callable[[], object], node: Node) -> None:
"""Attach a finalizer to the given node.
Expand All @@ -517,7 +522,7 @@ def teardown_exact(self, nextitem: Optional[Item]) -> None:
while self.stack:
if list(self.stack.keys()) == needed_collectors[: len(self.stack)]:
break
node, (finalizers, prepare_exc) = self.stack.popitem()
node, (finalizers, _) = self.stack.popitem()
while finalizers:
fin = finalizers.pop()
try:
Expand Down
6 changes: 3 additions & 3 deletions testing/python/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def test_funcarg_basic(self, pytester: Pytester) -> None:
item = pytester.getitem(Path("test_funcarg_basic.py"))
assert isinstance(item, Function)
# Execute's item's setup, which fills fixtures.
item.session._setupstate.prepare(item)
item.session._setupstate.setup(item)
del item.funcargs["request"]
assert len(get_public_names(item.funcargs)) == 2
assert item.funcargs["some"] == "test_func"
Expand Down Expand Up @@ -827,7 +827,7 @@ def test_func(something): pass
req = item._request

# Execute item's setup.
item.session._setupstate.prepare(item)
item.session._setupstate.setup(item)

with pytest.raises(pytest.FixtureLookupError):
req.getfixturevalue("notexists")
Expand Down Expand Up @@ -855,7 +855,7 @@ def test_func(something): pass
"""
)
assert isinstance(item, Function)
item.session._setupstate.prepare(item)
item.session._setupstate.setup(item)
item._request._fillfixtures()
# successively check finalization calls
parent = item.getparent(pytest.Module)
Expand Down
14 changes: 7 additions & 7 deletions testing/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def test_setup(self, pytester: Pytester) -> None:
item = pytester.getitem("def test_func(): pass")
ss = item.session._setupstate
values = [1]
ss.prepare(item)
ss.setup(item)
ss.addfinalizer(values.pop, item)
assert values
ss.teardown_exact(None)
Expand All @@ -34,7 +34,7 @@ def test_setup(self, pytester: Pytester) -> None:
def test_teardown_exact_stack_empty(self, pytester: Pytester) -> None:
item = pytester.getitem("def test_func(): pass")
ss = item.session._setupstate
ss.prepare(item)
ss.setup(item)
ss.teardown_exact(None)
ss.teardown_exact(None)
ss.teardown_exact(None)
Expand All @@ -49,9 +49,9 @@ def test_func(): pass
)
ss = item.session._setupstate
with pytest.raises(ValueError):
ss.prepare(item)
ss.setup(item)
with pytest.raises(ValueError):
ss.prepare(item)
ss.setup(item)

def test_teardown_multiple_one_fails(self, pytester: Pytester) -> None:
r = []
Expand All @@ -67,7 +67,7 @@ def fin3():

item = pytester.getitem("def test_func(): pass")
ss = item.session._setupstate
ss.prepare(item)
ss.setup(item)
ss.addfinalizer(fin1, item)
ss.addfinalizer(fin2, item)
ss.addfinalizer(fin3, item)
Expand All @@ -87,7 +87,7 @@ def fin2():

item = pytester.getitem("def test_func(): pass")
ss = item.session._setupstate
ss.prepare(item)
ss.setup(item)
ss.addfinalizer(fin1, item)
ss.addfinalizer(fin2, item)
with pytest.raises(Exception) as err:
Expand All @@ -106,7 +106,7 @@ def fin_module():
item = pytester.getitem("def test_func(): pass")
mod = item.listchain()[-2]
ss = item.session._setupstate
ss.prepare(item)
ss.setup(item)
ss.addfinalizer(fin_module, mod)
ss.addfinalizer(fin_func, item)
with pytest.raises(Exception, match="oops1"):
Expand Down

0 comments on commit 1003bea

Please sign in to comment.