Skip to content

Commit 9e75901

Browse files
committed
resolve #2049
1 parent f24f20a commit 9e75901

File tree

2 files changed

+105
-1
lines changed

2 files changed

+105
-1
lines changed

src/_pytest/setupplan.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ def pytest_addoption(parser):
1616
def pytest_fixture_setup(fixturedef, request):
1717
# Will return a dummy fixture if the setuponly option is provided.
1818
if request.config.option.setupplan:
19-
fixturedef.cached_result = (None, None, None)
19+
my_cache_key = fixturedef.cache_key(request)
20+
fixturedef.cached_result = (None, my_cache_key, None)
2021
return fixturedef.cached_result
2122

2223

testing/python/setup_plan.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,106 @@ def test_arg(arg):
1717
result.stdout.fnmatch_lines(
1818
["*SETUP F arg*", "*test_arg (fixtures used: arg)", "*TEARDOWN F arg*"]
1919
)
20+
21+
22+
def test_show_multi_test_fixture_setup_and_teardown_correctly_simple(testdir):
23+
"""
24+
Verify that when a fixture lives for longer than a single test, --setup-plan
25+
correctly displays the SETUP/TEARDOWN indicators the right number of times.
26+
27+
As reported in https://github.com/pytest-dev/pytest/issues/2049
28+
--setup-plan was showing SETUP/TEARDOWN on every test, even when the fixture
29+
should persist through multiple tests.
30+
31+
(Note that this bug never affected actual test execution, which used the
32+
correct fixture lifetimes. It was purely a display bug for --setup-plan, and
33+
did not affect the related --setup-show or --setup-only.)
34+
"""
35+
testdir.makepyfile(
36+
"""
37+
import pytest
38+
39+
@pytest.fixture(scope = 'class')
40+
def fix():
41+
return object()
42+
43+
class TestClass:
44+
def test_one(self, fix):
45+
assert False
46+
47+
def test_two(self, fix):
48+
assert False
49+
"""
50+
)
51+
52+
result = testdir.runpytest("--setup-plan")
53+
assert result.ret == 0
54+
55+
setup_fragment = "SETUP C fix"
56+
setup_count = 0
57+
58+
teardown_fragment = "TEARDOWN C fix"
59+
teardown_count = 0
60+
61+
for line in result.stdout.lines:
62+
if setup_fragment in line:
63+
setup_count += 1
64+
if teardown_fragment in line:
65+
teardown_count += 1
66+
67+
# before the fix this tests, there would have been a setup/teardown
68+
# message for each test, so the counts would each have been 2
69+
assert setup_count == 1
70+
assert teardown_count == 1
71+
72+
73+
def test_show_multi_test_fixture_setup_and_teardown_same_as_setup_show(testdir):
74+
"""
75+
Verify that SETUP/TEARDOWN messages match what comes out of --setup-show.
76+
"""
77+
testdir.makepyfile(
78+
"""
79+
import pytest
80+
81+
@pytest.fixture(scope = 'session')
82+
def sess():
83+
return True
84+
85+
@pytest.fixture(scope = 'module')
86+
def mod():
87+
return True
88+
89+
@pytest.fixture(scope = 'class')
90+
def cls():
91+
return True
92+
93+
@pytest.fixture(scope = 'function')
94+
def func():
95+
return True
96+
97+
98+
def test_outside(sess, mod, cls, func):
99+
assert True
100+
101+
102+
class TestCls:
103+
def test_one(self, sess, mod, cls, func):
104+
assert True
105+
106+
def test_two(self, sess, mod, cls, func):
107+
assert True
108+
"""
109+
)
110+
111+
plan_result = testdir.runpytest("--setup-plan")
112+
show_result = testdir.runpytest("--setup-show")
113+
114+
# the number and text of these lines should be identical
115+
plan_lines = [
116+
l for l in plan_result.stdout.lines if "SETUP" in l or "TEARDOWN" in l
117+
]
118+
show_lines = [
119+
l for l in show_result.stdout.lines if "SETUP" in l or "TEARDOWN" in l
120+
]
121+
122+
assert plan_lines == show_lines

0 commit comments

Comments
 (0)