Skip to content

Commit ebc6e47

Browse files
committed
gh-120388: Improve deprecation warning message, when test returns non-None
1 parent 755dab7 commit ebc6e47

File tree

5 files changed

+52
-6
lines changed

5 files changed

+52
-6
lines changed

Lib/test/test_unittest/test_async_case.py

+3
Original file line numberDiff line numberDiff line change
@@ -312,18 +312,21 @@ async def test3(self):
312312
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
313313
self.assertIn('test1', str(w.warning))
314314
self.assertEqual(w.filename, __file__)
315+
self.assertIn("(<class 'int'>)", str(w.warning))
315316

316317
with self.assertWarns(DeprecationWarning) as w:
317318
Test('test2').run()
318319
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
319320
self.assertIn('test2', str(w.warning))
320321
self.assertEqual(w.filename, __file__)
322+
self.assertIn("(<class 'async_generator'>)", str(w.warning))
321323

322324
with self.assertWarns(DeprecationWarning) as w:
323325
Test('test3').run()
324326
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
325327
self.assertIn('test3', str(w.warning))
326328
self.assertEqual(w.filename, __file__)
329+
self.assertIn(f'({Nothing})', str(w.warning))
327330

328331
def test_cleanups_interleave_order(self):
329332
events = []

Lib/test/test_unittest/test_case.py

+22
Original file line numberDiff line numberDiff line change
@@ -325,18 +325,40 @@ def test3(self):
325325
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
326326
self.assertIn('test1', str(w.warning))
327327
self.assertEqual(w.filename, __file__)
328+
self.assertIn("(<class 'int'>)", str(w.warning))
328329

329330
with self.assertWarns(DeprecationWarning) as w:
330331
Foo('test2').run()
331332
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
332333
self.assertIn('test2', str(w.warning))
333334
self.assertEqual(w.filename, __file__)
335+
self.assertIn("(<class 'generator'>)", str(w.warning))
334336

335337
with self.assertWarns(DeprecationWarning) as w:
336338
Foo('test3').run()
337339
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
338340
self.assertIn('test3', str(w.warning))
339341
self.assertEqual(w.filename, __file__)
342+
self.assertIn(f'({Nothing})', str(w.warning))
343+
344+
def test_deprecation_of_return_val_from_test_async_method(self):
345+
class Foo(unittest.TestCase):
346+
async def test1(self):
347+
return 1
348+
349+
with self.assertWarns(DeprecationWarning) as w:
350+
Foo('test1').run()
351+
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
352+
self.assertIn('test1', str(w.warning))
353+
self.assertEqual(w.filename, __file__)
354+
self.assertIn("(<class 'coroutine'>)", str(w.warning))
355+
self.assertIn(
356+
(
357+
"a coroutine is returned, "
358+
"maybe you forgot to use IsolatedAsyncioTestCase base class?"
359+
),
360+
str(w.warning),
361+
)
340362

341363
def _check_call_order__subtests(self, result, events, expected_events):
342364
class Foo(Test.LoggingTestCase):

Lib/unittest/async_case.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,13 @@ def _callSetUp(self):
9090
self._callAsync(self.asyncSetUp)
9191

9292
def _callTestMethod(self, method):
93-
if self._callMaybeAsync(method) is not None:
94-
warnings.warn(f'It is deprecated to return a value that is not None from a '
95-
f'test case ({method})', DeprecationWarning, stacklevel=4)
93+
if (result := self._callMaybeAsync(method)) is not None:
94+
msg = (
95+
'It is deprecated to return a value that is not None, '
96+
f'got: ({type(result)}) from a '
97+
f'test case ({method})',
98+
)
99+
warnings.warn(msg, DeprecationWarning, stacklevel=4)
96100

97101
def _callTearDown(self):
98102
self._callAsync(self.asyncTearDown)

Lib/unittest/case.py

+17-3
Original file line numberDiff line numberDiff line change
@@ -603,9 +603,23 @@ def _callSetUp(self):
603603
self.setUp()
604604

605605
def _callTestMethod(self, method):
606-
if method() is not None:
607-
warnings.warn(f'It is deprecated to return a value that is not None from a '
608-
f'test case ({method})', DeprecationWarning, stacklevel=3)
606+
if (result := method()) is not None:
607+
import inspect
608+
from unittest.async_case import IsolatedAsyncioTestCase
609+
msg = (
610+
'It is deprecated to return a value that is not None, '
611+
f'got: ({type(result)}) from a '
612+
f'test case ({method})'
613+
)
614+
if (
615+
inspect.iscoroutine(result)
616+
and not isinstance(self, IsolatedAsyncioTestCase)
617+
):
618+
msg += (
619+
'; a coroutine is returned, maybe you forgot to use '
620+
'IsolatedAsyncioTestCase base class?'
621+
)
622+
warnings.warn(msg, DeprecationWarning, stacklevel=3)
609623

610624
def _callTearDown(self):
611625
self.tearDown()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Improve a warning message when a test method in :mod:`unittest` returns
2+
something other than ``None``. Now we show the returned object type and
3+
optional asyncio-related tip.

0 commit comments

Comments
 (0)