From c73701de7292b7de0fee5b7f82a610d7515c18a4 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 18 Jun 2014 01:36:32 +0200 Subject: asyncio: Refactor tests: add a base TestCase class --- Lib/asyncio/test_utils.py | 18 +++++ Lib/test/test_asyncio/test_base_events.py | 11 +-- Lib/test/test_asyncio/test_events.py | 14 ++-- Lib/test/test_asyncio/test_futures.py | 25 ++---- Lib/test/test_asyncio/test_locks.py | 68 +++++------------ Lib/test/test_asyncio/test_proactor_events.py | 7 +- Lib/test/test_asyncio/test_queues.py | 32 +++----- Lib/test/test_asyncio/test_selector_events.py | 21 +++--- Lib/test/test_asyncio/test_streams.py | 5 +- Lib/test/test_asyncio/test_subprocess.py | 10 ++- Lib/test/test_asyncio/test_tasks.py | 105 +++++++++----------------- Lib/test/test_asyncio/test_unix_events.py | 40 +++++----- Lib/test/test_asyncio/test_windows_events.py | 8 +- 13 files changed, 145 insertions(+), 219 deletions(-) diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py index 1062bae..d9c7ae2 100644 --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -11,6 +11,7 @@ import sys import tempfile import threading import time +import unittest from unittest import mock from http.server import HTTPServer @@ -379,3 +380,20 @@ def get_function_source(func): if source is None: raise ValueError("unable to get the source of %r" % (func,)) return source + + +class TestCase(unittest.TestCase): + def set_event_loop(self, loop, *, cleanup=True): + assert loop is not None + # ensure that the event loop is passed explicitly in asyncio + events.set_event_loop(None) + if cleanup: + self.addCleanup(loop.close) + + def new_test_loop(self, gen=None): + loop = TestLoop(gen) + self.set_event_loop(loop) + return loop + + def tearDown(self): + events.set_event_loop(None) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index fb28b87..059b41c 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -19,12 +19,12 @@ MOCK_ANY = mock.ANY PY34 = sys.version_info >= (3, 4) -class BaseEventLoopTests(unittest.TestCase): +class BaseEventLoopTests(test_utils.TestCase): def setUp(self): self.loop = base_events.BaseEventLoop() self.loop._selector = mock.Mock() - asyncio.set_event_loop(None) + self.set_event_loop(self.loop) def test_not_implemented(self): m = mock.Mock() @@ -548,14 +548,11 @@ class MyDatagramProto(asyncio.DatagramProtocol): self.done.set_result(None) -class BaseEventLoopWithSelectorTests(unittest.TestCase): +class BaseEventLoopWithSelectorTests(test_utils.TestCase): def setUp(self): self.loop = asyncio.new_event_loop() - asyncio.set_event_loop(None) - - def tearDown(self): - self.loop.close() + self.set_event_loop(self.loop) @mock.patch('asyncio.base_events.socket') def test_create_connection_multiple_errors(self, m_socket): diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 2262a75..37e45e1 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -224,7 +224,7 @@ class EventLoopTestsMixin: def setUp(self): super().setUp() self.loop = self.create_event_loop() - asyncio.set_event_loop(None) + self.set_event_loop(self.loop) def tearDown(self): # just in case if we have transport close callbacks @@ -1629,14 +1629,14 @@ class SubprocessTestsMixin: if sys.platform == 'win32': - class SelectEventLoopTests(EventLoopTestsMixin, unittest.TestCase): + class SelectEventLoopTests(EventLoopTestsMixin, test_utils.TestCase): def create_event_loop(self): return asyncio.SelectorEventLoop() class ProactorEventLoopTests(EventLoopTestsMixin, SubprocessTestsMixin, - unittest.TestCase): + test_utils.TestCase): def create_event_loop(self): return asyncio.ProactorEventLoop() @@ -1691,7 +1691,7 @@ else: if hasattr(selectors, 'KqueueSelector'): class KqueueEventLoopTests(UnixEventLoopTestsMixin, SubprocessTestsMixin, - unittest.TestCase): + test_utils.TestCase): def create_event_loop(self): return asyncio.SelectorEventLoop( @@ -1716,7 +1716,7 @@ else: if hasattr(selectors, 'EpollSelector'): class EPollEventLoopTests(UnixEventLoopTestsMixin, SubprocessTestsMixin, - unittest.TestCase): + test_utils.TestCase): def create_event_loop(self): return asyncio.SelectorEventLoop(selectors.EpollSelector()) @@ -1724,7 +1724,7 @@ else: if hasattr(selectors, 'PollSelector'): class PollEventLoopTests(UnixEventLoopTestsMixin, SubprocessTestsMixin, - unittest.TestCase): + test_utils.TestCase): def create_event_loop(self): return asyncio.SelectorEventLoop(selectors.PollSelector()) @@ -1732,7 +1732,7 @@ else: # Should always exist. class SelectEventLoopTests(UnixEventLoopTestsMixin, SubprocessTestsMixin, - unittest.TestCase): + test_utils.TestCase): def create_event_loop(self): return asyncio.SelectorEventLoop(selectors.SelectSelector()) diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index 399e8f4..a230d61 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -13,14 +13,10 @@ def _fakefunc(f): return f -class FutureTests(unittest.TestCase): +class FutureTests(test_utils.TestCase): def setUp(self): - self.loop = test_utils.TestLoop() - asyncio.set_event_loop(None) - - def tearDown(self): - self.loop.close() + self.loop = self.new_test_loop() def test_initial_state(self): f = asyncio.Future(loop=self.loop) @@ -30,12 +26,9 @@ class FutureTests(unittest.TestCase): self.assertTrue(f.cancelled()) def test_init_constructor_default_loop(self): - try: - asyncio.set_event_loop(self.loop) - f = asyncio.Future() - self.assertIs(f._loop, self.loop) - finally: - asyncio.set_event_loop(None) + asyncio.set_event_loop(self.loop) + f = asyncio.Future() + self.assertIs(f._loop, self.loop) def test_constructor_positional(self): # Make sure Future doesn't accept a positional argument @@ -264,14 +257,10 @@ class FutureTests(unittest.TestCase): self.assertTrue(f2.cancelled()) -class FutureDoneCallbackTests(unittest.TestCase): +class FutureDoneCallbackTests(test_utils.TestCase): def setUp(self): - self.loop = test_utils.TestLoop() - asyncio.set_event_loop(None) - - def tearDown(self): - self.loop.close() + self.loop = self.new_test_loop() def run_briefly(self): test_utils.run_briefly(self.loop) diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index f542463..9d50a71 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -17,14 +17,10 @@ STR_RGX_REPR = ( RGX_REPR = re.compile(STR_RGX_REPR) -class LockTests(unittest.TestCase): +class LockTests(test_utils.TestCase): def setUp(self): - self.loop = test_utils.TestLoop() - asyncio.set_event_loop(None) - - def tearDown(self): - self.loop.close() + self.loop = self.new_test_loop() def test_ctor_loop(self): loop = mock.Mock() @@ -35,12 +31,9 @@ class LockTests(unittest.TestCase): self.assertIs(lock._loop, self.loop) def test_ctor_noloop(self): - try: - asyncio.set_event_loop(self.loop) - lock = asyncio.Lock() - self.assertIs(lock._loop, self.loop) - finally: - asyncio.set_event_loop(None) + asyncio.set_event_loop(self.loop) + lock = asyncio.Lock() + self.assertIs(lock._loop, self.loop) def test_repr(self): lock = asyncio.Lock(loop=self.loop) @@ -240,14 +233,10 @@ class LockTests(unittest.TestCase): self.assertFalse(lock.locked()) -class EventTests(unittest.TestCase): +class EventTests(test_utils.TestCase): def setUp(self): - self.loop = test_utils.TestLoop() - asyncio.set_event_loop(None) - - def tearDown(self): - self.loop.close() + self.loop = self.new_test_loop() def test_ctor_loop(self): loop = mock.Mock() @@ -258,12 +247,9 @@ class EventTests(unittest.TestCase): self.assertIs(ev._loop, self.loop) def test_ctor_noloop(self): - try: - asyncio.set_event_loop(self.loop) - ev = asyncio.Event() - self.assertIs(ev._loop, self.loop) - finally: - asyncio.set_event_loop(None) + asyncio.set_event_loop(self.loop) + ev = asyncio.Event() + self.assertIs(ev._loop, self.loop) def test_repr(self): ev = asyncio.Event(loop=self.loop) @@ -376,14 +362,10 @@ class EventTests(unittest.TestCase): self.assertTrue(t.result()) -class ConditionTests(unittest.TestCase): +class ConditionTests(test_utils.TestCase): def setUp(self): - self.loop = test_utils.TestLoop() - asyncio.set_event_loop(None) - - def tearDown(self): - self.loop.close() + self.loop = self.new_test_loop() def test_ctor_loop(self): loop = mock.Mock() @@ -394,12 +376,9 @@ class ConditionTests(unittest.TestCase): self.assertIs(cond._loop, self.loop) def test_ctor_noloop(self): - try: - asyncio.set_event_loop(self.loop) - cond = asyncio.Condition() - self.assertIs(cond._loop, self.loop) - finally: - asyncio.set_event_loop(None) + asyncio.set_event_loop(self.loop) + cond = asyncio.Condition() + self.assertIs(cond._loop, self.loop) def test_wait(self): cond = asyncio.Condition(loop=self.loop) @@ -678,14 +657,10 @@ class ConditionTests(unittest.TestCase): self.assertFalse(cond.locked()) -class SemaphoreTests(unittest.TestCase): +class SemaphoreTests(test_utils.TestCase): def setUp(self): - self.loop = test_utils.TestLoop() - asyncio.set_event_loop(None) - - def tearDown(self): - self.loop.close() + self.loop = self.new_test_loop() def test_ctor_loop(self): loop = mock.Mock() @@ -696,12 +671,9 @@ class SemaphoreTests(unittest.TestCase): self.assertIs(sem._loop, self.loop) def test_ctor_noloop(self): - try: - asyncio.set_event_loop(self.loop) - sem = asyncio.Semaphore() - self.assertIs(sem._loop, self.loop) - finally: - asyncio.set_event_loop(None) + asyncio.set_event_loop(self.loop) + sem = asyncio.Semaphore() + self.assertIs(sem._loop, self.loop) def test_initial_value_zero(self): sem = asyncio.Semaphore(0, loop=self.loop) diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 5bf24a4..ddfceae 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -12,10 +12,10 @@ from asyncio.proactor_events import _ProactorDuplexPipeTransport from asyncio import test_utils -class ProactorSocketTransportTests(unittest.TestCase): +class ProactorSocketTransportTests(test_utils.TestCase): def setUp(self): - self.loop = test_utils.TestLoop() + self.loop = self.new_test_loop() self.proactor = mock.Mock() self.loop._proactor = self.proactor self.protocol = test_utils.make_test_protocol(asyncio.Protocol) @@ -343,7 +343,7 @@ class ProactorSocketTransportTests(unittest.TestCase): tr.close() -class BaseProactorEventLoopTests(unittest.TestCase): +class BaseProactorEventLoopTests(test_utils.TestCase): def setUp(self): self.sock = mock.Mock(socket.socket) @@ -356,6 +356,7 @@ class BaseProactorEventLoopTests(unittest.TestCase): return (self.ssock, self.csock) self.loop = EventLoop(self.proactor) + self.set_event_loop(self.loop, cleanup=False) @mock.patch.object(BaseProactorEventLoop, 'call_soon') @mock.patch.object(BaseProactorEventLoop, '_socketpair') diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py index 820234d..32c90f4 100644 --- a/Lib/test/test_asyncio/test_queues.py +++ b/Lib/test/test_asyncio/test_queues.py @@ -7,14 +7,10 @@ import asyncio from asyncio import test_utils -class _QueueTestBase(unittest.TestCase): +class _QueueTestBase(test_utils.TestCase): def setUp(self): - self.loop = test_utils.TestLoop() - asyncio.set_event_loop(None) - - def tearDown(self): - self.loop.close() + self.loop = self.new_test_loop() class QueueBasicTests(_QueueTestBase): @@ -32,8 +28,7 @@ class QueueBasicTests(_QueueTestBase): self.assertAlmostEqual(0.2, when) yield 0.1 - loop = test_utils.TestLoop(gen) - self.addCleanup(loop.close) + loop = self.new_test_loop(gen) q = asyncio.Queue(loop=loop) self.assertTrue(fn(q).startswith('