@@ -17,3 +17,106 @@ def test_arg(arg):
17
17
result .stdout .fnmatch_lines (
18
18
["*SETUP F arg*" , "*test_arg (fixtures used: arg)" , "*TEARDOWN F arg*" ]
19
19
)
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