diff options
author | Ćukasz Langa <lukasz@langa.pl> | 2021-09-22 16:42:15 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-22 16:42:15 (GMT) |
commit | 44396aaba9b92b3a38a4b422a000d1a8eb05185a (patch) | |
tree | 7ec3abf49d9f3497bf3fe4afa836f2a7bb050db9 /Lib/unittest/test | |
parent | 8c1e1da565bca9cec792323eb728e288715ef7c4 (diff) | |
download | cpython-44396aaba9b92b3a38a4b422a000d1a8eb05185a.zip cpython-44396aaba9b92b3a38a4b422a000d1a8eb05185a.tar.gz cpython-44396aaba9b92b3a38a4b422a000d1a8eb05185a.tar.bz2 |
[3.10] bpo-45238: Fix unittest.IsolatedAsyncioTestCase.debug() (GH-28449) (GH-28521)
It runs now asynchronous methods and callbacks.
If it fails, doCleanups() can be called for cleaning up.
(cherry picked from commit ecb6922ff2d56476a6cfb0941ae55aca5e7fae3d)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Diffstat (limited to 'Lib/unittest/test')
-rw-r--r-- | Lib/unittest/test/test_async_case.py | 206 |
1 files changed, 155 insertions, 51 deletions
diff --git a/Lib/unittest/test/test_async_case.py b/Lib/unittest/test/test_async_case.py index 6e48b9e..e46b99f 100644 --- a/Lib/unittest/test/test_async_case.py +++ b/Lib/unittest/test/test_async_case.py @@ -1,5 +1,10 @@ import asyncio import unittest +from test import support + + +class MyException(Exception): + pass def tearDownModule(): @@ -7,9 +12,14 @@ def tearDownModule(): class TestAsyncCase(unittest.TestCase): - def test_full_cycle(self): - events = [] + maxDiff = None + + def tearDown(self): + # Ensure that IsolatedAsyncioTestCase instances are destroyed before + # starting a new event loop + support.gc_collect() + def test_full_cycle(self): class Test(unittest.IsolatedAsyncioTestCase): def setUp(self): self.assertEqual(events, []) @@ -18,12 +28,13 @@ class TestAsyncCase(unittest.TestCase): async def asyncSetUp(self): self.assertEqual(events, ['setUp']) events.append('asyncSetUp') + self.addAsyncCleanup(self.on_cleanup1) async def test_func(self): self.assertEqual(events, ['setUp', 'asyncSetUp']) events.append('test') - self.addAsyncCleanup(self.on_cleanup) + self.addAsyncCleanup(self.on_cleanup2) async def asyncTearDown(self): self.assertEqual(events, ['setUp', @@ -38,34 +49,48 @@ class TestAsyncCase(unittest.TestCase): 'asyncTearDown']) events.append('tearDown') - async def on_cleanup(self): + async def on_cleanup1(self): + self.assertEqual(events, ['setUp', + 'asyncSetUp', + 'test', + 'asyncTearDown', + 'tearDown', + 'cleanup2']) + events.append('cleanup1') + + async def on_cleanup2(self): self.assertEqual(events, ['setUp', 'asyncSetUp', 'test', 'asyncTearDown', 'tearDown']) - events.append('cleanup') + events.append('cleanup2') + events = [] test = Test("test_func") - test.run() - self.assertEqual(events, ['setUp', - 'asyncSetUp', - 'test', - 'asyncTearDown', - 'tearDown', - 'cleanup']) + result = test.run() + self.assertEqual(result.errors, []) + self.assertEqual(result.failures, []) + expected = ['setUp', 'asyncSetUp', 'test', + 'asyncTearDown', 'tearDown', 'cleanup2', 'cleanup1'] + self.assertEqual(events, expected) - def test_exception_in_setup(self): events = [] + test = Test("test_func") + test.debug() + self.assertEqual(events, expected) + test.doCleanups() + self.assertEqual(events, expected) + def test_exception_in_setup(self): class Test(unittest.IsolatedAsyncioTestCase): async def asyncSetUp(self): events.append('asyncSetUp') - raise Exception() + self.addAsyncCleanup(self.on_cleanup) + raise MyException() async def test_func(self): events.append('test') - self.addAsyncCleanup(self.on_cleanup) async def asyncTearDown(self): events.append('asyncTearDown') @@ -74,21 +99,34 @@ class TestAsyncCase(unittest.TestCase): events.append('cleanup') + events = [] test = Test("test_func") - test.run() - self.assertEqual(events, ['asyncSetUp']) + result = test.run() + self.assertEqual(events, ['asyncSetUp', 'cleanup']) + self.assertIs(result.errors[0][0], test) + self.assertIn('MyException', result.errors[0][1]) - def test_exception_in_test(self): events = [] + test = Test("test_func") + try: + test.debug() + except MyException: + pass + else: + self.fail('Expected a MyException exception') + self.assertEqual(events, ['asyncSetUp']) + test.doCleanups() + self.assertEqual(events, ['asyncSetUp', 'cleanup']) + def test_exception_in_test(self): class Test(unittest.IsolatedAsyncioTestCase): async def asyncSetUp(self): events.append('asyncSetUp') async def test_func(self): events.append('test') - raise Exception() self.addAsyncCleanup(self.on_cleanup) + raise MyException() async def asyncTearDown(self): events.append('asyncTearDown') @@ -96,13 +134,26 @@ class TestAsyncCase(unittest.TestCase): async def on_cleanup(self): events.append('cleanup') + events = [] test = Test("test_func") - test.run() - self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown']) + result = test.run() + self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup']) + self.assertIs(result.errors[0][0], test) + self.assertIn('MyException', result.errors[0][1]) - def test_exception_in_test_after_adding_cleanup(self): events = [] + test = Test("test_func") + try: + test.debug() + except MyException: + pass + else: + self.fail('Expected a MyException exception') + self.assertEqual(events, ['asyncSetUp', 'test']) + test.doCleanups() + self.assertEqual(events, ['asyncSetUp', 'test', 'cleanup']) + def test_exception_in_tear_down(self): class Test(unittest.IsolatedAsyncioTestCase): async def asyncSetUp(self): events.append('asyncSetUp') @@ -110,62 +161,73 @@ class TestAsyncCase(unittest.TestCase): async def test_func(self): events.append('test') self.addAsyncCleanup(self.on_cleanup) - raise Exception() async def asyncTearDown(self): events.append('asyncTearDown') + raise MyException() async def on_cleanup(self): events.append('cleanup') + events = [] test = Test("test_func") - test.run() + result = test.run() self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup']) + self.assertIs(result.errors[0][0], test) + self.assertIn('MyException', result.errors[0][1]) - def test_exception_in_tear_down(self): events = [] - - class Test(unittest.IsolatedAsyncioTestCase): - async def asyncSetUp(self): - events.append('asyncSetUp') - - async def test_func(self): - events.append('test') - self.addAsyncCleanup(self.on_cleanup) - - async def asyncTearDown(self): - events.append('asyncTearDown') - raise Exception() - - async def on_cleanup(self): - events.append('cleanup') - test = Test("test_func") - test.run() + try: + test.debug() + except MyException: + pass + else: + self.fail('Expected a MyException exception') + self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown']) + test.doCleanups() self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup']) - def test_exception_in_tear_clean_up(self): - events = [] - class Test(unittest.IsolatedAsyncioTestCase): async def asyncSetUp(self): events.append('asyncSetUp') async def test_func(self): events.append('test') - self.addAsyncCleanup(self.on_cleanup) + self.addAsyncCleanup(self.on_cleanup1) + self.addAsyncCleanup(self.on_cleanup2) async def asyncTearDown(self): events.append('asyncTearDown') - async def on_cleanup(self): - events.append('cleanup') - raise Exception() + async def on_cleanup1(self): + events.append('cleanup1') + raise MyException('some error') + + async def on_cleanup2(self): + events.append('cleanup2') + raise MyException('other error') + events = [] test = Test("test_func") - test.run() - self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup']) + result = test.run() + self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup2', 'cleanup1']) + self.assertIs(result.errors[0][0], test) + self.assertIn('MyException: other error', result.errors[0][1]) + self.assertIn('MyException: some error', result.errors[1][1]) + + events = [] + test = Test("test_func") + try: + test.debug() + except MyException: + pass + else: + self.fail('Expected a MyException exception') + self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup2']) + test.doCleanups() + self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup2', 'cleanup1']) def test_cleanups_interleave_order(self): events = [] @@ -235,7 +297,49 @@ class TestAsyncCase(unittest.TestCase): output = test.run() self.assertTrue(cancelled) + def test_debug_cleanup_same_loop(self): + class Test(unittest.IsolatedAsyncioTestCase): + async def asyncSetUp(self): + async def coro(): + await asyncio.sleep(0) + fut = asyncio.ensure_future(coro()) + self.addAsyncCleanup(self.cleanup, fut) + events.append('asyncSetUp') + + async def test_func(self): + events.append('test') + raise MyException() + async def asyncTearDown(self): + events.append('asyncTearDown') + + async def cleanup(self, fut): + try: + # Raises an exception if in different loop + await asyncio.wait([fut]) + events.append('cleanup') + except: + import traceback + traceback.print_exc() + raise + + events = [] + test = Test("test_func") + result = test.run() + self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup']) + self.assertIn('MyException', result.errors[0][1]) + + events = [] + test = Test("test_func") + try: + test.debug() + except MyException: + pass + else: + self.fail('Expected a MyException exception') + self.assertEqual(events, ['asyncSetUp', 'test']) + test.doCleanups() + self.assertEqual(events, ['asyncSetUp', 'test', 'cleanup']) if __name__ == "__main__": |