From 17009e910538b9c3709d302f54c2d10eb245cf38 Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Thu, 5 Mar 2020 14:26:33 +0100 Subject: [PATCH] Refs #31224 -- Added autoconversion of test async methods. --- django/test/testcases.py | 7 +++++++ tests/asgi/tests.py | 8 -------- tests/async/tests.py | 4 +--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/django/test/testcases.py b/django/test/testcases.py index 23459f22cd..2c24708a3b 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -1,3 +1,4 @@ +import asyncio import difflib import json import posixpath @@ -16,6 +17,8 @@ from urllib.parse import ( ) from urllib.request import url2pathname +from asgiref.sync import async_to_sync + from django.apps import apps from django.conf import settings from django.core import mail @@ -257,6 +260,10 @@ class SimpleTestCase(unittest.TestCase): getattr(testMethod, "__unittest_skip__", False) ) + # Convert async test methods. + if asyncio.iscoroutinefunction(testMethod): + setattr(self, self._testMethodName, async_to_sync(testMethod)) + if not skipped: try: self._pre_setup() diff --git a/tests/asgi/tests.py b/tests/asgi/tests.py index 3a26d3130f..fada34d0d8 100644 --- a/tests/asgi/tests.py +++ b/tests/asgi/tests.py @@ -2,7 +2,6 @@ import asyncio import sys from unittest import skipIf -from asgiref.sync import async_to_sync from asgiref.testing import ApplicationCommunicator from django.core.asgi import get_asgi_application @@ -34,7 +33,6 @@ class ASGITest(SimpleTestCase): def tearDown(self): request_started.connect(close_old_connections) - @async_to_sync async def test_get_asgi_application(self): """ get_asgi_application() returns a functioning ASGI callable. @@ -58,7 +56,6 @@ class ASGITest(SimpleTestCase): self.assertEqual(response_body['type'], 'http.response.body') self.assertEqual(response_body['body'], b'Hello World!') - @async_to_sync async def test_file_response(self): """ Makes sure that FileResponse works over ASGI. @@ -86,7 +83,6 @@ class ASGITest(SimpleTestCase): self.assertEqual(response_body['type'], 'http.response.body') self.assertEqual(response_body['body'], test_file_contents) - @async_to_sync async def test_headers(self): application = get_asgi_application() communicator = ApplicationCommunicator( @@ -116,7 +112,6 @@ class ASGITest(SimpleTestCase): self.assertEqual(response_body['type'], 'http.response.body') self.assertEqual(response_body['body'], b'From Scotland,Wales') - @async_to_sync async def test_get_query_string(self): application = get_asgi_application() for query_string in (b'name=Andrew', 'name=Andrew'): @@ -133,7 +128,6 @@ class ASGITest(SimpleTestCase): self.assertEqual(response_body['type'], 'http.response.body') self.assertEqual(response_body['body'], b'Hello Andrew!') - @async_to_sync async def test_disconnect(self): application = get_asgi_application() communicator = ApplicationCommunicator(application, self._get_scope(path='/')) @@ -141,7 +135,6 @@ class ASGITest(SimpleTestCase): with self.assertRaises(asyncio.TimeoutError): await communicator.receive_output() - @async_to_sync async def test_wrong_connection_type(self): application = get_asgi_application() communicator = ApplicationCommunicator( @@ -153,7 +146,6 @@ class ASGITest(SimpleTestCase): with self.assertRaisesMessage(ValueError, msg): await communicator.receive_output() - @async_to_sync async def test_non_unicode_query_string(self): application = get_asgi_application() communicator = ApplicationCommunicator( diff --git a/tests/async/tests.py b/tests/async/tests.py index 86ed504c57..783fbdd080 100644 --- a/tests/async/tests.py +++ b/tests/async/tests.py @@ -27,7 +27,6 @@ class CacheTest(SimpleTestCase): @skipIf(sys.platform == 'win32' and (3, 8, 0) < sys.version_info < (3, 8, 1), 'https://bugs.python.org/issue38563') class DatabaseConnectionTest(SimpleTestCase): """A database connection cannot be used in an async context.""" - @async_to_sync async def test_get_async_connection(self): with self.assertRaises(SynchronousOnlyOperation): list(SimpleModel.objects.all()) @@ -43,7 +42,6 @@ class AsyncUnsafeTest(SimpleTestCase): def dangerous_method(self): return True - @async_to_sync async def test_async_unsafe(self): # async_unsafe decorator catches bad access and returns the right # message. @@ -55,7 +53,7 @@ class AsyncUnsafeTest(SimpleTestCase): self.dangerous_method() @mock.patch.dict(os.environ, {'DJANGO_ALLOW_ASYNC_UNSAFE': 'true'}) - @async_to_sync + @async_to_sync # mock.patch() is not async-aware. async def test_async_unsafe_suppressed(self): # Decorator doesn't trigger check when the environment variable to # suppress it is set.