-
-
Notifications
You must be signed in to change notification settings - Fork 372
Description
At work we have an internal AssertRaises class which I'd like to kill it off in favor of the newer trio.testing.RaisesGroup (added in #2898). However, it has one neat feature which we use fairly regularly to test exceptions arising specifically when exiting some (potentially async) context manager, often one which wraps a nursery:
with RaisesGroup(..., must_reach_point=True) as assert_raises:
async with some_async_context_manager:
...
assert_raises.must_reach_this_point()
# passes iff we raise the error on exitObviously it's an error to call .must_reach_this_point() without specifying must_reach_point=True or vice-versa, or to call it twice. If must_reach_point=True then the RaisesGroup should not catch or otherwise handle any exceptions raised before .must_reach_this_point() is called.
You can currently implement something similar inline, with:
reached_point = False
with RaisesGroup(...) as excinfo:
async with some_async_context_manager:
...
reached_point = True
if not reached_point:
raise AssertionError("Raised expected exception, but never executed CM body") from excinfo.valuebut a mere three lines of code each time adds up pretty quickly. I think the main effect of this is to change from checking the exception was raised at all to checking it was raised during exit, which seems pretty valuable to me.
A small downside is it may encourage too-widely-scoped with RaisesGroup; in principle we could check at runtime that the .must_reach_this_point() is inside a with block which is itself inside the RaisesGroup , but I don't think it's worth the trouble.