-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Description
The current behavior on the released pytest version is:
- if
matchfails,pytest.raisesraises anAssertionError - if the type differs, the exception propagates through.
- if no exception was raised,
pytest.raisesraisespytest.Failed
#13192 complicated this for several reasons, and having RaisesGroup adhere to point 2 was untenable. It became non-trivial to figure out why the "type" of an exceptiongroup with several nested exceptions and groups couldn't get matched against another group. It also became very weird when the "type" started to include matches itself, and it would've necessitated extra logic to figure out if RaisesGroup(RaisesExc(ValueError, match="foo")) failed because of the type or the match in RaisesExc. Or in even weirder cases where it fails for both reasons:
with RaisesGroup(RaisesExc(ValueError), RaisesExc(match="foo")):
raise ExceptionGroup(TypeError("bar"), TypeError("bar"))
So RaisesGroup will raise an exception in all cases.
We're then faced with how this should affect pytest.raises. #13192 made it raise an AssertionError upon type difference (and if check fails), but this would likely be considered a breaking change. I personally think it's very different if a test fails because I got a completely unexpected exception, versus a different exception than the one I specifically expected in a raises block; but I don't think that's a huge win.
The other downside of keeping current behavior is it becoming an arbitrary-but-for-historic-reasons difference between raises and RaisesGroup.
In either case, the original exception is accessible in the __cause__ attribute and adapting code should be straightforward.
I do also find the distinction between raising pytest.Fail versus AssertionError quite arbitrary, and think they should be unified. My instinct would be for all failures to be pytest.Fail, as AssertionError usually signals to users that an explicit assert has failed. We could make this change backward-compatible by having the exception raised inherit from both AssertionError and pytest.Fail if we really want to.
This also matters for ExceptionInfo.match, which ideally should share logic with raises for string matching - but currently doesn't. It currently raises an AssertionError on failure.
tl;dr
- Should
raisespropagate the exception, or raiseAssertionError, orFail? - Is the distinction between raising different exception types useful, or confusing?
- Should
RaisesGroupraisepytest.FailorAssertionErrorwhen failing a match, regardless of reason?