Skip to content

Commit feffb1d

Browse files
committedFeb 7, 2022
trio_test_case: throw an exception if we forget to await a coroutine
Forgetting to await a coroutine may make a test do essentially nothing. We want to make sure that doesn't happen. Probably raise_unraisables should be done automatically by unittest.TestCase. Ideally, forgetting an await would be an error at the Python level, see also python-trio/pytest-trio#86
1 parent 886e708 commit feffb1d

File tree

1 file changed

+29
-1
lines changed

1 file changed

+29
-1
lines changed
 

‎python/rsyscall/tests/trio_test_case.py

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
11
"A trio-enabled variant of unittest.TestCase"
22
import trio
33
import unittest
4+
import contextlib
45
import functools
6+
import sys
57
import types
8+
import warnings
69
from trio._core._run import Nursery
710
from rsyscall import local_process, Process
811

12+
@contextlib.contextmanager
13+
def raise_unraisables():
14+
unraisables = []
15+
try:
16+
orig_unraisablehook, sys.unraisablehook = sys.unraisablehook, unraisables.append
17+
yield
18+
finally:
19+
sys.unraisablehook = orig_unraisablehook
20+
if unraisables:
21+
raise trio.MultiError([unr.exc_value for unr in unraisables])
22+
923
class TrioTestCase(unittest.TestCase):
1024
"A trio-enabled variant of unittest.TestCase"
1125
nursery: Nursery
@@ -43,7 +57,21 @@ async def test_with_setup() -> None:
4357
nursery.cancel_scope.cancel()
4458
@functools.wraps(test_with_setup)
4559
def sync_test_with_setup(self) -> None:
46-
trio.run(test_with_setup)
60+
# Throw an exception if there were any "coroutine was never awaited" warnings, to fail the test.
61+
# See https://github.com/python-trio/pytest-trio/issues/86
62+
# We also need raise_unraisables, otherwise the exception is suppressed, since it's in __del__
63+
with raise_unraisables():
64+
# Restore the old warning filter after the test.
65+
with warnings.catch_warnings():
66+
warnings.filterwarnings('error', message='.*was never awaited', category=RuntimeWarning)
67+
trio.run(test_with_setup)
4768
setattr(self, methodName, types.MethodType(sync_test_with_setup, self))
4869
super().__init__(methodName)
4970

71+
class Test(unittest.TestCase):
72+
def test_coro_warning(self) -> None:
73+
class Test(TrioTestCase):
74+
async def test(self):
75+
trio.sleep(0)
76+
with self.assertRaises(RuntimeWarning):
77+
Test('test').test()

0 commit comments

Comments
 (0)
Please sign in to comment.