Python "raises in exception group" context manager for tests
Here’s a Python testing utility function for asserting on an expected
Exception
type from within an
ExceptionGroup:
from contextlib import contextmanager
@contextmanager
def raises_in_group(
expected_exception: type[Exception],
match_message: str = "",
):
"""
Like pytest.raises, but for an Exception inside an ExceptionGroup, for
example coming from asyncio.TaskGroup.
"""
matched_type = []
matched_message = []
try:
yield
except* expected_exception as e:
assert isinstance(e, ExceptionGroup)
matched_type = [exp for exp in e.exceptions if isinstance(exp, expected_exception)]
matched_message = [exp for exp in matched_type if match_message in str(exp)]
assert len(matched_type) >= 1, f"Expected at least one {expected_exception} exception."
assert (
len(matched_message) >= 1
), f"Expected at least one {expected_exception} exception matching '{match_message}'."
It can be used in test cases in a similar way to pytest.raises, like this:
with raises_in_group(ValueError, "foobar error message"):
do_something()
Python introduced ExceptionGroup
to handle situations where multiple
exceptions might be raised during a process and the user wants to be aware of
all of them to decide how to proceed. As an example, the asyncio.TaskGroup
context manager uses ExceptionGroup
to handle multiple exceptions occurring in
different tasks.