summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRan Benita <ran@unusedvar.com>2021-02-08 13:56:04 +0200
committerGitHub <noreply@github.com>2021-02-08 13:56:04 +0200
commit1003beaffa4e9139068a3e363ea3da42e6d90b26 (patch)
treee81bcedac7181b27925db8567e7add4128270023
parentf85427b92af14268c1c8e2adf83903e9bb604a98 (diff)
parent5822888d735e2cd617225686611275fa8fbafbea (diff)
downloadpytest-1003beaffa4e9139068a3e363ea3da42e6d90b26.tar.gz
Merge pull request #8323 from bluetech/setupstate-refactor-3
runner: a few more tweaks to SetupState
-rw-r--r--src/_pytest/fixtures.py2
-rw-r--r--src/_pytest/hookspec.py6
-rw-r--r--src/_pytest/runner.py29
-rw-r--r--testing/python/fixtures.py6
-rw-r--r--testing/test_runner.py14
5 files changed, 31 insertions, 26 deletions
diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py
index 6a57fffd1..0521d7361 100644
--- a/src/_pytest/fixtures.py
+++ b/src/_pytest/fixtures.py
@@ -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 = {}
diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py
index 41c12a2cc..b0b8fd53d 100644
--- a/src/_pytest/hookspec.py
+++ b/src/_pytest/hookspec.py
@@ -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.
"""
diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py
index ae76a2472..e43dd2dc8 100644
--- a/src/_pytest/runner.py
+++ b/src/_pytest/runner.py
@@ -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]
@@ -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:
@@ -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()
@@ -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()
@@ -477,23 +479,26 @@ class SetupState:
],
] = {}
- 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.
@@ -517,7 +522,7 @@ class SetupState:
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:
diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py
index 3d78ebf58..3d5099c53 100644
--- a/testing/python/fixtures.py
+++ b/testing/python/fixtures.py
@@ -131,7 +131,7 @@ class TestFillFixtures:
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"
@@ -827,7 +827,7 @@ class TestRequestBasic:
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")
@@ -855,7 +855,7 @@ class TestRequestBasic:
"""
)
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)
diff --git a/testing/test_runner.py b/testing/test_runner.py
index e3f286307..abb87c6d3 100644
--- a/testing/test_runner.py
+++ b/testing/test_runner.py
@@ -25,7 +25,7 @@ class TestSetupState:
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)
@@ -34,7 +34,7 @@ class TestSetupState:
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)
@@ -49,9 +49,9 @@ class TestSetupState:
)
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 = []
@@ -67,7 +67,7 @@ class TestSetupState:
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)
@@ -87,7 +87,7 @@ class TestSetupState:
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:
@@ -106,7 +106,7 @@ class TestSetupState:
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"):