Skip to content

Commit

Permalink
pythongh-120388: Improve deprecation warning message, when test retur…
Browse files Browse the repository at this point in the history
…ns non-None
  • Loading branch information
sobolevn committed Jun 12, 2024
1 parent 755dab7 commit 7fae4cc
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 6 deletions.
3 changes: 3 additions & 0 deletions Lib/test/test_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -1495,6 +1495,9 @@ class SpamEnum(Enum):
spam = nonmember(SpamEnumIsInner)
self.assertTrue(SpamEnum.spam is SpamEnumIsInner)

async def test_some(self):
...

def test_nested_classes_in_enum_with_member(self):
"""Support locally-defined nested classes."""
class Outer(Enum):
Expand Down
3 changes: 3 additions & 0 deletions Lib/test/test_unittest/test_async_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,18 +312,21 @@ async def test3(self):
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
self.assertIn('test1', str(w.warning))
self.assertEqual(w.filename, __file__)
self.assertIn("(<class 'int'>)", str(w.warning))

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

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

def test_cleanups_interleave_order(self):
events = []
Expand Down
22 changes: 22 additions & 0 deletions Lib/test/test_unittest/test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,18 +325,40 @@ def test3(self):
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
self.assertIn('test1', str(w.warning))
self.assertEqual(w.filename, __file__)
self.assertIn("(<class 'int'>)", str(w.warning))

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

with self.assertWarns(DeprecationWarning) as w:
Foo('test3').run()
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
self.assertIn('test3', str(w.warning))
self.assertEqual(w.filename, __file__)
self.assertIn(f'({Nothing})', str(w.warning))

def test_deprecation_of_return_val_from_test_async_method(self):
class Foo(unittest.TestCase):
async def test1(self):
return 1

with self.assertWarns(DeprecationWarning) as w:
Foo('test1').run()
self.assertIn('It is deprecated to return a value that is not None', str(w.warning))
self.assertIn('test1', str(w.warning))
self.assertEqual(w.filename, __file__)
self.assertIn("(<class 'coroutine'>)", str(w.warning))
self.assertIn(
(
"a coroutine is returned, "
"maybe you forgot to use IsolatedAsyncioTestCase base class?"
),
str(w.warning),
)

def _check_call_order__subtests(self, result, events, expected_events):
class Foo(Test.LoggingTestCase):
Expand Down
10 changes: 7 additions & 3 deletions Lib/unittest/async_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,13 @@ def _callSetUp(self):
self._callAsync(self.asyncSetUp)

def _callTestMethod(self, method):
if self._callMaybeAsync(method) is not None:
warnings.warn(f'It is deprecated to return a value that is not None from a '
f'test case ({method})', DeprecationWarning, stacklevel=4)
if (result := self._callMaybeAsync(method)) is not None:
msg = (
'It is deprecated to return a value that is not None, '
f'got: ({type(result)}) from a '
f'test case ({method})',
)
warnings.warn(msg, DeprecationWarning, stacklevel=4)

def _callTearDown(self):
self._callAsync(self.asyncTearDown)
Expand Down
20 changes: 17 additions & 3 deletions Lib/unittest/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,9 +603,23 @@ def _callSetUp(self):
self.setUp()

def _callTestMethod(self, method):
if method() is not None:
warnings.warn(f'It is deprecated to return a value that is not None from a '
f'test case ({method})', DeprecationWarning, stacklevel=3)
if (result := method()) is not None:
import inspect
from unittest.async_case import IsolatedAsyncioTestCase
msg = (
'It is deprecated to return a value that is not None, '
f'got: ({type(result)}) from a '
f'test case ({method})'
)
if (
inspect.iscoroutine(result)
and not isinstance(self, IsolatedAsyncioTestCase)
):
msg += (
'; a coroutine is returned, maybe you forgot to use '
'IsolatedAsyncioTestCase base class?'
)
warnings.warn(msg, DeprecationWarning, stacklevel=3)

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

0 comments on commit 7fae4cc

Please sign in to comment.