From 901085dec40a71c2ffd4b63832b1a1fda242e5ef Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Thu, 19 Aug 2021 21:10:50 -0400 Subject: [PATCH 1/7] added two unit tests for deprecation of test return values --- Lib/unittest/test/test_async_case.py | 10 ++++++++++ Lib/unittest/test/test_case.py | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/Lib/unittest/test/test_async_case.py b/Lib/unittest/test/test_async_case.py index 6e48b9e4bfed36..96c4ed22c31547 100644 --- a/Lib/unittest/test/test_async_case.py +++ b/Lib/unittest/test/test_async_case.py @@ -167,6 +167,16 @@ async def on_cleanup(self): test.run() self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup']) + def test_deprecation_of_return_val_from_test(self): + # Issue 41322 - deprecate return of value!=None from a test + class Test(unittest.IsolatedAsyncioTestCase): + async def test(self): + return 1 + + with self.assertWarnsRegex(DeprecationWarning, + 'It is deprecated to return a value!=None'): + Test('test').run() + def test_cleanups_interleave_order(self): events = [] diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py index b8aca92a8ebe9f..6ee1bcdbca83aa 100644 --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -306,6 +306,21 @@ def test(self): Foo('test').run() + def test_deprecation_of_return_val_from_test(self): + # Issue 41322 - deprecate return of value!=None from a test + class Foo(unittest.TestCase): + def test(self): + return 1 + def test2(self): + yield 1 + + with self.assertWarnsRegex(DeprecationWarning, + 'It is deprecated to return a value!=None'): + Foo('test').run() + with self.assertWarnsRegex(DeprecationWarning, + 'It is deprecated to return a value!=None'): + Foo('test2').run() + def _check_call_order__subtests(self, result, events, expected_events): class Foo(Test.LoggingTestCase): def test(self): From f2aa37972b89a6ea284b6b90fbb075a59e961fea Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Fri, 20 Aug 2021 17:00:32 -0400 Subject: [PATCH 2/7] updated warnings and tests --- Lib/unittest/async_case.py | 2 +- Lib/unittest/case.py | 2 +- Lib/unittest/test/test_async_case.py | 6 ++++-- Lib/unittest/test/test_case.py | 12 ++++++++---- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Lib/unittest/async_case.py b/Lib/unittest/async_case.py index cc404cc06f8b65..bfc68a76e84d93 100644 --- a/Lib/unittest/async_case.py +++ b/Lib/unittest/async_case.py @@ -65,7 +65,7 @@ def _callSetUp(self): def _callTestMethod(self, method): if self._callMaybeAsync(method) is not None: warnings.warn(f'It is deprecated to return a value!=None from a ' - f'test case ({method})', DeprecationWarning) + f'test case ({method})', DeprecationWarning, stacklevel=4) def _callTearDown(self): self._callAsync(self.asyncTearDown) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py index 3c771c0ca8e102..943b6dcf6eed58 100644 --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -548,7 +548,7 @@ def _callSetUp(self): def _callTestMethod(self, method): if method() is not None: warnings.warn(f'It is deprecated to return a value!=None from a ' - f'test case ({method})', DeprecationWarning) + f'test case ({method})', DeprecationWarning, stacklevel=3) def _callTearDown(self): self.tearDown() diff --git a/Lib/unittest/test/test_async_case.py b/Lib/unittest/test/test_async_case.py index 96c4ed22c31547..68d5ca21837404 100644 --- a/Lib/unittest/test/test_async_case.py +++ b/Lib/unittest/test/test_async_case.py @@ -173,9 +173,11 @@ class Test(unittest.IsolatedAsyncioTestCase): async def test(self): return 1 - with self.assertWarnsRegex(DeprecationWarning, - 'It is deprecated to return a value!=None'): + with self.assertWarns(DeprecationWarning) as w: Test('test').run() + self.assertIn('It is deprecated to return a value!=None', w.warnings[0].message.args[0]) + self.assertIn('test', w.warnings[0].message.args[0]) + self.assertIn(w.warnings[0].filename, __file__) def test_cleanups_interleave_order(self): events = [] diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py index 6ee1bcdbca83aa..33f382827c50fb 100644 --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -314,12 +314,16 @@ def test(self): def test2(self): yield 1 - with self.assertWarnsRegex(DeprecationWarning, - 'It is deprecated to return a value!=None'): + with self.assertWarns(DeprecationWarning) as w: Foo('test').run() - with self.assertWarnsRegex(DeprecationWarning, - 'It is deprecated to return a value!=None'): + self.assertIn('It is deprecated to return a value!=None', w.warnings[0].message.args[0]) + self.assertIn('test', w.warnings[0].message.args[0]) + self.assertIn(w.warnings[0].filename, __file__) + with self.assertWarns(DeprecationWarning) as w: Foo('test2').run() + self.assertIn('It is deprecated to return a value!=None', w.warnings[0].message.args[0]) + self.assertIn('test2', w.warnings[0].message.args[0]) + self.assertEqual(w.warnings[0].filename, __file__) def _check_call_order__subtests(self, result, events, expected_events): class Foo(Test.LoggingTestCase): From ab15abad423708903dca3391571e5106da007a1b Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Fri, 20 Aug 2021 17:06:04 -0400 Subject: [PATCH 3/7] add async generator test --- Lib/unittest/test/test_async_case.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Lib/unittest/test/test_async_case.py b/Lib/unittest/test/test_async_case.py index 68d5ca21837404..7dd036fc1eb846 100644 --- a/Lib/unittest/test/test_async_case.py +++ b/Lib/unittest/test/test_async_case.py @@ -172,12 +172,19 @@ def test_deprecation_of_return_val_from_test(self): class Test(unittest.IsolatedAsyncioTestCase): async def test(self): return 1 + async def test2(self): + yield 1 with self.assertWarns(DeprecationWarning) as w: Test('test').run() self.assertIn('It is deprecated to return a value!=None', w.warnings[0].message.args[0]) self.assertIn('test', w.warnings[0].message.args[0]) self.assertIn(w.warnings[0].filename, __file__) + with self.assertWarns(DeprecationWarning) as w: + Test('test2').run() + self.assertIn('It is deprecated to return a value!=None', w.warnings[0].message.args[0]) + self.assertIn('test', w.warnings[0].message.args[0]) + self.assertIn(w.warnings[0].filename, __file__) def test_cleanups_interleave_order(self): events = [] From 490b42d769d99c6a2c8bd4ccdbd32d1f221d1e53 Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Sun, 22 Aug 2021 09:34:13 -0400 Subject: [PATCH 4/7] updated normal and async tests --- Lib/unittest/test/test_async_case.py | 17 +++++++++-------- Lib/unittest/test/test_case.py | 17 +++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Lib/unittest/test/test_async_case.py b/Lib/unittest/test/test_async_case.py index 7dd036fc1eb846..00316ac392dd6b 100644 --- a/Lib/unittest/test/test_async_case.py +++ b/Lib/unittest/test/test_async_case.py @@ -170,21 +170,22 @@ async def on_cleanup(self): def test_deprecation_of_return_val_from_test(self): # Issue 41322 - deprecate return of value!=None from a test class Test(unittest.IsolatedAsyncioTestCase): - async def test(self): + async def test1(self): return 1 async def test2(self): yield 1 with self.assertWarns(DeprecationWarning) as w: - Test('test').run() - self.assertIn('It is deprecated to return a value!=None', w.warnings[0].message.args[0]) - self.assertIn('test', w.warnings[0].message.args[0]) - self.assertIn(w.warnings[0].filename, __file__) + Test('test1').run() + self.assertIn('It is deprecated to return a value!=None', str(w.warnings[0].message)) + self.assertIn('test1', str(w.warnings[0].message)) + self.assertEquals(w.warnings[0].filename, __file__) + with self.assertWarns(DeprecationWarning) as w: Test('test2').run() - self.assertIn('It is deprecated to return a value!=None', w.warnings[0].message.args[0]) - self.assertIn('test', w.warnings[0].message.args[0]) - self.assertIn(w.warnings[0].filename, __file__) + self.assertIn('It is deprecated to return a value!=None', str(w.warnings[0].message)) + self.assertIn('test2', str(w.warnings[0].message)) + self.assertEquals(w.warnings[0].filename, __file__) def test_cleanups_interleave_order(self): events = [] diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py index 33f382827c50fb..1706409ffae108 100644 --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -309,21 +309,22 @@ def test(self): def test_deprecation_of_return_val_from_test(self): # Issue 41322 - deprecate return of value!=None from a test class Foo(unittest.TestCase): - def test(self): + def test1(self): return 1 def test2(self): yield 1 with self.assertWarns(DeprecationWarning) as w: - Foo('test').run() - self.assertIn('It is deprecated to return a value!=None', w.warnings[0].message.args[0]) - self.assertIn('test', w.warnings[0].message.args[0]) - self.assertIn(w.warnings[0].filename, __file__) + Foo('test1').run() + self.assertIn('It is deprecated to return a value!=None', str(w.warnings[0].message)) + self.assertIn('test1', str(w.warnings[0].message)) + self.assertEquals(w.warnings[0].filename, __file__) + with self.assertWarns(DeprecationWarning) as w: Foo('test2').run() - self.assertIn('It is deprecated to return a value!=None', w.warnings[0].message.args[0]) - self.assertIn('test2', w.warnings[0].message.args[0]) - self.assertEqual(w.warnings[0].filename, __file__) + self.assertIn('It is deprecated to return a value!=None', str(w.warnings[0].message)) + self.assertIn('test2', str(w.warnings[0].message)) + self.assertEquals(w.warnings[0].filename, __file__) def _check_call_order__subtests(self, result, events, expected_events): class Foo(Test.LoggingTestCase): From da198f2b1b000096c9619f393b5be1eb36e68a55 Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Sun, 22 Aug 2021 12:01:24 -0400 Subject: [PATCH 5/7] fix ..Equals to ..Equal --- Lib/unittest/test/test_async_case.py | 4 ++-- Lib/unittest/test/test_case.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/unittest/test/test_async_case.py b/Lib/unittest/test/test_async_case.py index 00316ac392dd6b..93ef1997e0c99f 100644 --- a/Lib/unittest/test/test_async_case.py +++ b/Lib/unittest/test/test_async_case.py @@ -179,13 +179,13 @@ async def test2(self): Test('test1').run() self.assertIn('It is deprecated to return a value!=None', str(w.warnings[0].message)) self.assertIn('test1', str(w.warnings[0].message)) - self.assertEquals(w.warnings[0].filename, __file__) + self.assertEqual(w.warnings[0].filename, __file__) with self.assertWarns(DeprecationWarning) as w: Test('test2').run() self.assertIn('It is deprecated to return a value!=None', str(w.warnings[0].message)) self.assertIn('test2', str(w.warnings[0].message)) - self.assertEquals(w.warnings[0].filename, __file__) + self.assertEqual(w.warnings[0].filename, __file__) def test_cleanups_interleave_order(self): events = [] diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py index 1706409ffae108..f3cabe44d1c88e 100644 --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -318,13 +318,13 @@ def test2(self): Foo('test1').run() self.assertIn('It is deprecated to return a value!=None', str(w.warnings[0].message)) self.assertIn('test1', str(w.warnings[0].message)) - self.assertEquals(w.warnings[0].filename, __file__) + self.assertEqual(w.warnings[0].filename, __file__) with self.assertWarns(DeprecationWarning) as w: Foo('test2').run() self.assertIn('It is deprecated to return a value!=None', str(w.warnings[0].message)) self.assertIn('test2', str(w.warnings[0].message)) - self.assertEquals(w.warnings[0].filename, __file__) + self.assertEqual(w.warnings[0].filename, __file__) def _check_call_order__subtests(self, result, events, expected_events): class Foo(Test.LoggingTestCase): From e19793f31ca3f4914d4228c4731304c828cd856b Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Sun, 22 Aug 2021 12:12:23 -0400 Subject: [PATCH 6/7] add change note to unittest.rst --- Doc/library/unittest.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 99c2f6e029448e..2ccdeec73392cd 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -151,6 +151,10 @@ The above examples show the most commonly used :mod:`unittest` features which are sufficient to meet many everyday testing needs. The remainder of the documentation explores the full feature set from first principles. +.. versionchanged:: 3.11 + The behavior of returning a value from a test (other than the default ``None`` + value), is now deprecated. + .. _unittest-command-line-interface: From 872767e156788e11301e7dd2f748f927794fb18e Mon Sep 17 00:00:00 2001 From: andrei kulakov Date: Sun, 22 Aug 2021 12:21:22 -0400 Subject: [PATCH 7/7] add entry to WhatsNew --- Doc/library/unittest.rst | 4 ++-- Doc/whatsnew/3.11.rst | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 2ccdeec73392cd..f0fba94677a917 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -152,8 +152,8 @@ are sufficient to meet many everyday testing needs. The remainder of the documentation explores the full feature set from first principles. .. versionchanged:: 3.11 - The behavior of returning a value from a test (other than the default ``None`` - value), is now deprecated. + The behavior of returning a value from a test method (other than the default + ``None`` value), is now deprecated. .. _unittest-command-line-interface: diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 49b4364be9bd7f..cb8f84c4b625e5 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -395,3 +395,7 @@ Removed :func:`~gettext.install` are also removed, since they are only used for the ``l*gettext()`` functions. (Contributed by Dong-hee Na and Serhiy Storchaka in :issue:`44235`.) + +* The behavior of returning a value from a :class:`~unittest.TestCase` and + :class:`~unittest.IsolatedAsyncioTestCase` test methods (other than the default ``None`` + value), is now deprecated.