@@ -165,3 +165,56 @@ def test_stop_on_collection_errors(broken_testdir, broken_first):
165165 files .reverse ()
166166 result = broken_testdir .runpytest ("-v" , "--strict-markers" , "--stepwise" , * files )
167167 result .stdout .fnmatch_lines ("*errors during collection*" )
168+
169+
170+ def test_xfail_handling (testdir ):
171+ """Ensure normal xfail is ignored, and strict xfail interrupts the session in sw mode
172+
173+ (#5547)
174+ """
175+ contents = """
176+ import pytest
177+ def test_a(): pass
178+
179+ @pytest.mark.xfail(strict={strict})
180+ def test_b(): assert {assert_value}
181+
182+ def test_c(): pass
183+ def test_d(): pass
184+ """
185+ testdir .makepyfile (contents .format (assert_value = "0" , strict = "False" ))
186+ result = testdir .runpytest ("--sw" , "-v" )
187+ result .stdout .fnmatch_lines (
188+ [
189+ "*::test_a PASSED *" ,
190+ "*::test_b XFAIL *" ,
191+ "*::test_c PASSED *" ,
192+ "*::test_d PASSED *" ,
193+ "* 3 passed, 1 xfailed in *" ,
194+ ]
195+ )
196+
197+ testdir .makepyfile (contents .format (assert_value = "1" , strict = "True" ))
198+ result = testdir .runpytest ("--sw" , "-v" )
199+ result .stdout .fnmatch_lines (
200+ [
201+ "*::test_a PASSED *" ,
202+ "*::test_b FAILED *" ,
203+ "* Interrupted*" ,
204+ "* 1 failed, 1 passed in *" ,
205+ ]
206+ )
207+
208+ # because we are writing to the same file, mtime might not be affected enough to
209+ # invalidate the cache, making this next run flaky
210+ testdir .tmpdir .join ("__pycache__" ).remove ()
211+ testdir .makepyfile (contents .format (assert_value = "0" , strict = "True" ))
212+ result = testdir .runpytest ("--sw" , "-v" )
213+ result .stdout .fnmatch_lines (
214+ [
215+ "*::test_b XFAIL *" ,
216+ "*::test_c PASSED *" ,
217+ "*::test_d PASSED *" ,
218+ "* 2 passed, 1 deselected, 1 xfailed in *" ,
219+ ]
220+ )
0 commit comments