File tree Expand file tree Collapse file tree 3 files changed +52
-5
lines changed Expand file tree Collapse file tree 3 files changed +52
-5
lines changed Original file line number Diff line number Diff line change 2323from .._code import getfslineno
2424from ..compat import NOTSET
2525from ..compat import NotSetType
26+ from _pytest ._raises_group import AbstractMatcher
2627from _pytest .config import Config
2728from _pytest .deprecated import check_ispytest
2829from _pytest .deprecated import MARKED_FIXTURE
@@ -459,7 +460,10 @@ def __call__(
459460 * conditions : str | bool ,
460461 reason : str = ...,
461462 run : bool = ...,
462- raises : None | type [BaseException ] | tuple [type [BaseException ], ...] = ...,
463+ raises : None
464+ | type [BaseException ]
465+ | tuple [type [BaseException ], ...]
466+ | AbstractMatcher [BaseException ] = ...,
463467 strict : bool = ...,
464468 ) -> MarkDecorator : ...
465469
Original file line number Diff line number Diff line change 1212import traceback
1313from typing import Optional
1414
15+ from _pytest ._raises_group import AbstractMatcher
1516from _pytest .config import Config
1617from _pytest .config import hookimpl
1718from _pytest .config .argparsing import Parser
@@ -201,7 +202,12 @@ class Xfail:
201202 reason : str
202203 run : bool
203204 strict : bool
204- raises : tuple [type [BaseException ], ...] | None
205+ raises : (
206+ type [BaseException ]
207+ | tuple [type [BaseException ], ...]
208+ | AbstractMatcher [BaseException ]
209+ | None
210+ )
205211
206212
207213def evaluate_xfail_marks (item : Item ) -> Xfail | None :
@@ -277,11 +283,20 @@ def pytest_runtest_makereport(
277283 elif not rep .skipped and xfailed :
278284 if call .excinfo :
279285 raises = xfailed .raises
280- if raises is not None and not isinstance (call .excinfo .value , raises ):
281- rep .outcome = "failed"
282- else :
286+ if raises is None or (
287+ (
288+ isinstance (raises , (type , tuple ))
289+ and isinstance (call .excinfo .value , raises )
290+ )
291+ or (
292+ isinstance (raises , AbstractMatcher )
293+ and raises .matches (call .excinfo .value )
294+ )
295+ ):
283296 rep .outcome = "skipped"
284297 rep .wasxfail = xfailed .reason
298+ else :
299+ rep .outcome = "failed"
285300 elif call .when == "call" :
286301 if xfailed .strict :
287302 rep .outcome = "failed"
Original file line number Diff line number Diff line change 1111from _pytest ._raises_group import RaisesGroup
1212from _pytest ._raises_group import repr_callable
1313from _pytest .outcomes import Failed
14+ from _pytest .pytester import Pytester
1415import pytest
1516
1617
@@ -1135,3 +1136,30 @@ def test_assert_matches() -> None:
11351136
11361137 # but even if we add assert_matches, will people remember to use it?
11371138 # other than writing a linter rule, I don't think we can catch `assert Matcher(...).matches`
1139+
1140+
1141+ # https://github.com/pytest-dev/pytest/issues/12504
1142+ def test_xfail_raisesgroup (pytester : Pytester ) -> None :
1143+ pytester .makepyfile (
1144+ """
1145+ import pytest
1146+ @pytest.mark.xfail(raises=pytest.RaisesGroup(ValueError))
1147+ def test_foo() -> None:
1148+ raise ExceptionGroup("foo", [ValueError()])
1149+ """
1150+ )
1151+ result = pytester .runpytest ()
1152+ result .assert_outcomes (xfailed = 1 )
1153+
1154+
1155+ def test_xfail_Matcher (pytester : Pytester ) -> None :
1156+ pytester .makepyfile (
1157+ """
1158+ import pytest
1159+ @pytest.mark.xfail(raises=pytest.Matcher(ValueError))
1160+ def test_foo() -> None:
1161+ raise ValueError
1162+ """
1163+ )
1164+ result = pytester .runpytest ()
1165+ result .assert_outcomes (xfailed = 1 )
You can’t perform that action at this time.
0 commit comments