You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
rename AbstractMatcher -> AbstractRaises, Matcher->RaisesExc. Add docs on RaisesGroup&RaisesExc. Add warnings to group_contains. Remove group_contains example from getting-started page
Added :class:`pytest.RaisesGroup` (also export as ``pytest.raises_group``) and :class:`pytest.RaisesExc`, as an equivalent to :func:`pytest.raises` for expecting :exc:`ExceptionGroup`. It includes the ability to specify multiple different expected exceptions, the structure of nested exception groups, and flags for emulating :ref:`except* <except_star>`. See :ref:`assert-matching-exception-groups` and docstrings for more information.
:func:`pytest.mark.xfail` now accepts :class:`pytest.RaisesGroup` for the ``raises`` parameter when you expect an exception group. You can also pass a :class:`pytest.RaisesExc` if you e.g. want to make use of the ``check`` parameter.
Copy file name to clipboardExpand all lines: doc/en/how-to/assert.rst
+87-2
Original file line number
Diff line number
Diff line change
@@ -145,8 +145,93 @@ Notes:
145
145
146
146
.. _`assert-matching-exception-groups`:
147
147
148
-
Matching exception groups
149
-
~~~~~~~~~~~~~~~~~~~~~~~~~
148
+
Assertions about expected exception groups
149
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
150
+
151
+
When expecting a :exc:`BaseExceptionGroup` or :exc:`ExceptionGroup` you can use :class:`pytest.RaisesGroup`, also available as :class:`pytest.raises_group <pytest.RaisesGroup>`:
It accepts a ``match`` parameter, that checks against the group message, and a ``check`` parameter that takes an arbitrary callable which it passes the group to, and only succeeds if the callable returns ``True``.
163
+
164
+
.. code-block:: python
165
+
166
+
deftest_raisesgroup_match_and_check():
167
+
with pytest.raises_group(BaseException, match="my group msg"):
168
+
raise BaseExceptionGroup("my group msg", [KeyboardInterrupt()])
It is strict about structure and unwrapped exceptions, unlike :ref:`except* <except_star>`, so you might want to set the ``flatten_subgroups`` and/or ``allow_unwrapped`` parameters.
175
+
176
+
.. code-block:: python
177
+
178
+
deftest_structure():
179
+
with pytest.raises_group(pytest.raises_group(ValueError)):
with pytest.raises_group(ValueError, allow_unwrapped=True):
184
+
raiseValueError
185
+
186
+
To specify more details about the contained exception you can use :class:`pytest.RaisesExc`
187
+
188
+
.. code-block:: python
189
+
190
+
deftest_raises_exc():
191
+
with pytest.raises_group(pytest.RaisesExc(ValueError, match="foo")):
192
+
raise ExceptionGroup("", (ValueError("foo")))
193
+
194
+
They both supply a method :meth:`pytest.RaisesGroup.matches` :meth:`pytest.RaisesExc.matches` if you want to do matching outside of using it as a contextmanager. This can be helpful when checking ``.__context__`` or ``.__cause__``.
195
+
196
+
.. code-block:: python
197
+
198
+
deftest_matches():
199
+
exc =ValueError()
200
+
exc_group = ExceptionGroup("", [exc])
201
+
if RaisesGroup(ValueError).matches(exc_group):
202
+
...
203
+
# helpful error is available in `.fail_reason` if it fails to match
204
+
r = RaisesExc(ValueError)
205
+
assert r.matches(e), r.fail_reason
206
+
207
+
Check the documentation on :class:`pytest.RaisesGroup` and :class:`pytest.RaisesExc` for more details and examples.
208
+
209
+
``ExceptionInfo.group_contains()``
210
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
211
+
212
+
.. warning::
213
+
214
+
This helper makes it easy to check for the presence of specific exceptions, but it is very bad for checking that the group does *not* contain *any other exceptions*. So this will pass:
215
+
216
+
.. code-block:: python
217
+
218
+
classEXTREMELYBADERROR(BaseException):
219
+
"""This is a very bad error to miss"""
220
+
221
+
222
+
deftest_for_value_error():
223
+
with pytest.raises(ExceptionGroup) as excinfo:
224
+
excs = [ValueError()]
225
+
if very_unlucky():
226
+
excs.append(EXTREMELYBADERROR())
227
+
raise ExceptionGroup("", excs)
228
+
# this passes regardless of if there's other exceptions
229
+
assert excinfo.group_contains(ValueError)
230
+
# you can't simply list all exceptions you *don't* want to get here
231
+
232
+
233
+
There is no good way of using :func:`excinfo.group_contains() <pytest.ExceptionInfo.group_contains>` to ensure you're not getting *any* other exceptions than the one you expected.
234
+
You should instead use :class:`pytest.raises_group <pytest.RaisesGroup>`, see :ref:`assert-matching-exception-groups`.
150
235
151
236
You can also use the :func:`excinfo.group_contains() <pytest.ExceptionInfo.group_contains>`
152
237
method to test for exceptions returned as part of an :class:`ExceptionGroup`:
0 commit comments