@@ -145,6 +145,72 @@ def test_body():
145145 assert spans [1 ].get_tag (test .STATUS ) == test .Status .SKIP .value
146146 assert spans [1 ].get_tag (test .SKIP_REASON ) == "body"
147147
148+ def test_xfail_fails (self ):
149+ """Test xfail (expected failure) which fails, should be marked as pass."""
150+ py_file = self .testdir .makepyfile (
151+ """
152+ import pytest
153+
154+ @pytest.mark.xfail(reason="test should fail")
155+ def test_should_fail():
156+ assert 0
157+ """
158+ )
159+ file_name = os .path .basename (py_file .strpath )
160+ rec = self .inline_run ("--ddtrace" , file_name )
161+ # pytest records xfail as skipped
162+ rec .assertoutcome (skipped = 1 )
163+ spans = self .pop_spans ()
164+
165+ assert len (spans ) == 1
166+ assert spans [0 ].get_tag (test .STATUS ) == test .Status .PASS .value
167+ assert spans [0 ].get_tag (test .RESULT ) == test .Status .XFAIL .value
168+ assert spans [0 ].get_tag (test .XFAIL_REASON ) == "test should fail"
169+
170+ def test_xpass_not_strict (self ):
171+ """Test xpass (unexpected passing) with strict=False, should be marked as pass."""
172+ py_file = self .testdir .makepyfile (
173+ """
174+ import pytest
175+
176+ @pytest.mark.xfail(reason="test should fail")
177+ def test_should_fail():
178+ pass
179+ """
180+ )
181+ file_name = os .path .basename (py_file .strpath )
182+ rec = self .inline_run ("--ddtrace" , file_name )
183+ rec .assertoutcome (passed = 1 )
184+ spans = self .pop_spans ()
185+
186+ assert len (spans ) == 1
187+ assert spans [0 ].get_tag (test .STATUS ) == test .Status .PASS .value
188+ assert spans [0 ].get_tag (test .RESULT ) == test .Status .XPASS .value
189+ assert spans [0 ].get_tag (test .XFAIL_REASON ) == "test should fail"
190+
191+ def test_xpass_strict (self ):
192+ """Test xpass (unexpected passing) with strict=True, should be marked as fail."""
193+ py_file = self .testdir .makepyfile (
194+ """
195+ import pytest
196+
197+ @pytest.mark.xfail(reason="test should fail", strict=True)
198+ def test_should_fail():
199+ pass
200+ """
201+ )
202+ file_name = os .path .basename (py_file .strpath )
203+ rec = self .inline_run ("--ddtrace" , file_name )
204+ rec .assertoutcome (failed = 1 )
205+ spans = self .pop_spans ()
206+
207+ assert len (spans ) == 1
208+ assert spans [0 ].get_tag (test .STATUS ) == test .Status .FAIL .value
209+ assert spans [0 ].get_tag (test .RESULT ) == test .Status .XPASS .value
210+ # Note: xpass (strict=True) does not mark the reason with result.wasxfail but into result.longrepr,
211+ # however this provides the entire traceback/error into longrepr.
212+ assert "test should fail" in spans [0 ].get_tag (test .XFAIL_REASON )
213+
148214 def test_tags (self ):
149215 """Test ddspan tags."""
150216 py_file = self .testdir .makepyfile (
0 commit comments