summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/unittest.rst8
-rw-r--r--Lib/test/test_unittest/test_async_case.py14
-rw-r--r--Lib/unittest/async_case.py7
-rw-r--r--Misc/NEWS.d/next/Library/2023-10-12-15-16-44.gh-issue-110774.AdCb5A.rst1
4 files changed, 28 insertions, 2 deletions
diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst
index 21abc58..c90c554 100644
--- a/Doc/library/unittest.rst
+++ b/Doc/library/unittest.rst
@@ -1571,6 +1571,14 @@ Test cases
.. versionadded:: 3.8
+ .. attribute:: loop_factory
+
+ The *loop_factory* passed to :class:`asyncio.Runner`. Override
+ in subclasses with :class:`asyncio.EventLoop` to avoid using the
+ asyncio policy system.
+
+ .. versionadded:: 3.13
+
.. coroutinemethod:: asyncSetUp()
Method called to prepare the test fixture. This is called after :meth:`setUp`.
diff --git a/Lib/test/test_unittest/test_async_case.py b/Lib/test/test_unittest/test_async_case.py
index a465103..ba1ab83 100644
--- a/Lib/test/test_unittest/test_async_case.py
+++ b/Lib/test/test_unittest/test_async_case.py
@@ -484,5 +484,19 @@ class TestAsyncCase(unittest.TestCase):
result = test.run()
self.assertTrue(result.wasSuccessful())
+ def test_loop_factory(self):
+ asyncio.set_event_loop_policy(None)
+
+ class TestCase1(unittest.IsolatedAsyncioTestCase):
+ loop_factory = asyncio.EventLoop
+
+ async def test_demo1(self):
+ pass
+
+ test = TestCase1('test_demo1')
+ result = test.run()
+ self.assertTrue(result.wasSuccessful())
+ self.assertIsNone(support.maybe_get_event_loop_policy())
+
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/unittest/async_case.py b/Lib/unittest/async_case.py
index bd2a471..63ff6a5 100644
--- a/Lib/unittest/async_case.py
+++ b/Lib/unittest/async_case.py
@@ -25,12 +25,15 @@ class IsolatedAsyncioTestCase(TestCase):
# them inside the same task.
# Note: the test case modifies event loop policy if the policy was not instantiated
- # yet.
+ # yet, unless loop_factory=asyncio.EventLoop is set.
# asyncio.get_event_loop_policy() creates a default policy on demand but never
# returns None
# I believe this is not an issue in user level tests but python itself for testing
# should reset a policy in every test module
# by calling asyncio.set_event_loop_policy(None) in tearDownModule()
+ # or set loop_factory=asyncio.EventLoop
+
+ loop_factory = None
def __init__(self, methodName='runTest'):
super().__init__(methodName)
@@ -118,7 +121,7 @@ class IsolatedAsyncioTestCase(TestCase):
def _setupAsyncioRunner(self):
assert self._asyncioRunner is None, 'asyncio runner is already initialized'
- runner = asyncio.Runner(debug=True)
+ runner = asyncio.Runner(debug=True, loop_factory=self.loop_factory)
self._asyncioRunner = runner
def _tearDownAsyncioRunner(self):
diff --git a/Misc/NEWS.d/next/Library/2023-10-12-15-16-44.gh-issue-110774.AdCb5A.rst b/Misc/NEWS.d/next/Library/2023-10-12-15-16-44.gh-issue-110774.AdCb5A.rst
new file mode 100644
index 0000000..a5a9fed
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-10-12-15-16-44.gh-issue-110774.AdCb5A.rst
@@ -0,0 +1 @@
+Support setting the :class:`asyncio.Runner` loop_factory kwarg in :class:`unittest.IsolatedAsyncioTestCase`