Refs #31224 -- Added autoconversion of test async methods.

This commit is contained in:
Andrew Godwin 2020-03-05 14:26:33 +01:00 committed by Mariusz Felisiak
parent 2f53d324de
commit 17009e9105
3 changed files with 8 additions and 11 deletions

View File

@ -1,3 +1,4 @@
import asyncio
import difflib import difflib
import json import json
import posixpath import posixpath
@ -16,6 +17,8 @@ from urllib.parse import (
) )
from urllib.request import url2pathname from urllib.request import url2pathname
from asgiref.sync import async_to_sync
from django.apps import apps from django.apps import apps
from django.conf import settings from django.conf import settings
from django.core import mail from django.core import mail
@ -257,6 +260,10 @@ class SimpleTestCase(unittest.TestCase):
getattr(testMethod, "__unittest_skip__", False) getattr(testMethod, "__unittest_skip__", False)
) )
# Convert async test methods.
if asyncio.iscoroutinefunction(testMethod):
setattr(self, self._testMethodName, async_to_sync(testMethod))
if not skipped: if not skipped:
try: try:
self._pre_setup() self._pre_setup()

View File

@ -2,7 +2,6 @@ import asyncio
import sys import sys
from unittest import skipIf from unittest import skipIf
from asgiref.sync import async_to_sync
from asgiref.testing import ApplicationCommunicator from asgiref.testing import ApplicationCommunicator
from django.core.asgi import get_asgi_application from django.core.asgi import get_asgi_application
@ -34,7 +33,6 @@ class ASGITest(SimpleTestCase):
def tearDown(self): def tearDown(self):
request_started.connect(close_old_connections) request_started.connect(close_old_connections)
@async_to_sync
async def test_get_asgi_application(self): async def test_get_asgi_application(self):
""" """
get_asgi_application() returns a functioning ASGI callable. 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['type'], 'http.response.body')
self.assertEqual(response_body['body'], b'Hello World!') self.assertEqual(response_body['body'], b'Hello World!')
@async_to_sync
async def test_file_response(self): async def test_file_response(self):
""" """
Makes sure that FileResponse works over ASGI. 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['type'], 'http.response.body')
self.assertEqual(response_body['body'], test_file_contents) self.assertEqual(response_body['body'], test_file_contents)
@async_to_sync
async def test_headers(self): async def test_headers(self):
application = get_asgi_application() application = get_asgi_application()
communicator = ApplicationCommunicator( communicator = ApplicationCommunicator(
@ -116,7 +112,6 @@ class ASGITest(SimpleTestCase):
self.assertEqual(response_body['type'], 'http.response.body') self.assertEqual(response_body['type'], 'http.response.body')
self.assertEqual(response_body['body'], b'From Scotland,Wales') self.assertEqual(response_body['body'], b'From Scotland,Wales')
@async_to_sync
async def test_get_query_string(self): async def test_get_query_string(self):
application = get_asgi_application() application = get_asgi_application()
for query_string in (b'name=Andrew', 'name=Andrew'): 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['type'], 'http.response.body')
self.assertEqual(response_body['body'], b'Hello Andrew!') self.assertEqual(response_body['body'], b'Hello Andrew!')
@async_to_sync
async def test_disconnect(self): async def test_disconnect(self):
application = get_asgi_application() application = get_asgi_application()
communicator = ApplicationCommunicator(application, self._get_scope(path='/')) communicator = ApplicationCommunicator(application, self._get_scope(path='/'))
@ -141,7 +135,6 @@ class ASGITest(SimpleTestCase):
with self.assertRaises(asyncio.TimeoutError): with self.assertRaises(asyncio.TimeoutError):
await communicator.receive_output() await communicator.receive_output()
@async_to_sync
async def test_wrong_connection_type(self): async def test_wrong_connection_type(self):
application = get_asgi_application() application = get_asgi_application()
communicator = ApplicationCommunicator( communicator = ApplicationCommunicator(
@ -153,7 +146,6 @@ class ASGITest(SimpleTestCase):
with self.assertRaisesMessage(ValueError, msg): with self.assertRaisesMessage(ValueError, msg):
await communicator.receive_output() await communicator.receive_output()
@async_to_sync
async def test_non_unicode_query_string(self): async def test_non_unicode_query_string(self):
application = get_asgi_application() application = get_asgi_application()
communicator = ApplicationCommunicator( communicator = ApplicationCommunicator(

View File

@ -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') @skipIf(sys.platform == 'win32' and (3, 8, 0) < sys.version_info < (3, 8, 1), 'https://bugs.python.org/issue38563')
class DatabaseConnectionTest(SimpleTestCase): class DatabaseConnectionTest(SimpleTestCase):
"""A database connection cannot be used in an async context.""" """A database connection cannot be used in an async context."""
@async_to_sync
async def test_get_async_connection(self): async def test_get_async_connection(self):
with self.assertRaises(SynchronousOnlyOperation): with self.assertRaises(SynchronousOnlyOperation):
list(SimpleModel.objects.all()) list(SimpleModel.objects.all())
@ -43,7 +42,6 @@ class AsyncUnsafeTest(SimpleTestCase):
def dangerous_method(self): def dangerous_method(self):
return True return True
@async_to_sync
async def test_async_unsafe(self): async def test_async_unsafe(self):
# async_unsafe decorator catches bad access and returns the right # async_unsafe decorator catches bad access and returns the right
# message. # message.
@ -55,7 +53,7 @@ class AsyncUnsafeTest(SimpleTestCase):
self.dangerous_method() self.dangerous_method()
@mock.patch.dict(os.environ, {'DJANGO_ALLOW_ASYNC_UNSAFE': 'true'}) @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): async def test_async_unsafe_suppressed(self):
# Decorator doesn't trigger check when the environment variable to # Decorator doesn't trigger check when the environment variable to
# suppress it is set. # suppress it is set.