diff --git a/CHANGES/5515.misc b/CHANGES/5515.misc new file mode 100644 index 00000000000..e3d810b17f6 --- /dev/null +++ b/CHANGES/5515.misc @@ -0,0 +1 @@ +Deprecate ``@unittest_run_loop``. This behaviour is now the default. diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index 20abe2c8088..4cb70c8cb22 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -2,12 +2,12 @@ import asyncio import contextlib -import functools import gc import inspect import os import socket import sys +import warnings from abc import ABC, abstractmethod from types import TracebackType from typing import ( @@ -472,17 +472,16 @@ async def get_client(self, server: TestServer) -> TestClient: def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any: """A decorator dedicated to use with asynchronous methods of an - AioHTTPTestCase. + AioHTTPTestCase in aiohttp <3.8. - Handles executing an asynchronous function, using - the self.loop of the AioHTTPTestCase. + In 3.8+, this does nothing. """ - - @functools.wraps(func, *args, **kwargs) - def new_func(self: Any, *inner_args: Any, **inner_kwargs: Any) -> Any: - return self.loop.run_until_complete(func(self, *inner_args, **inner_kwargs)) - - return new_func + warnings.warn( + "Decorator `@unittest_run_loop` is no longer needed in aiohttp 3.8+", + DeprecationWarning, + stacklevel=2, + ) + return func _LOOP_FACTORY = Callable[[], asyncio.AbstractEventLoop] diff --git a/docs/testing.rst b/docs/testing.rst index d722f3aef39..1cf316a3965 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -243,7 +243,7 @@ Unittest To test applications with the standard library's unittest or unittest-based functionality, the AioHTTPTestCase is provided:: - from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop + from aiohttp.test_utils import AioHTTPTestCase from aiohttp import web class MyAppTestCase(AioHTTPTestCase): @@ -259,26 +259,11 @@ functionality, the AioHTTPTestCase is provided:: app.router.add_get('/', hello) return app - # the unittest_run_loop decorator can be used in tandem with - # the AioHTTPTestCase to simplify running - # tests that are asynchronous - @unittest_run_loop async def test_example(self): - resp = await self.client.request("GET", "/") - assert resp.status == 200 - text = await resp.text() - assert "Hello, world" in text - - # a vanilla example - def test_example_vanilla(self): - async def test_get_route(): - url = "/" - resp = await self.client.request("GET", url) - assert resp.status == 200 + async with self.client.request("GET", "/") as resp: + self.assertEqual(resp.status, 200) text = await resp.text() - assert "Hello, world" in text - - self.loop.run_until_complete(test_get_route()) + self.assertIn("Hello, world", text) .. class:: AioHTTPTestCase @@ -361,16 +346,13 @@ functionality, the AioHTTPTestCase is provided:: .. note:: The ``TestClient``'s methods are asynchronous: you have to - execute function on the test client using asynchronous methods. - - A basic test class wraps every test method by - :func:`unittest_run_loop` decorator:: + execute functions on the test client using asynchronous methods.:: class TestA(AioHTTPTestCase): - @unittest_run_loop async def test_f(self): - resp = await self.client.get('/') + async with self.client.get('/') as resp: + body = await resp.text() .. decorator:: unittest_run_loop: @@ -381,6 +363,10 @@ functionality, the AioHTTPTestCase is provided:: Handles executing an asynchronous function, using the :attr:`AioHTTPTestCase.loop` of the :class:`AioHTTPTestCase`. + .. deprecated:: 3.8 + In 3.8+ :class:`AioHTTPTestCase` inherits from :class:`unittest.IsolatedAsyncioTestCase` + making this decorator unneeded. It is now a no-op. + Faking request object --------------------- diff --git a/tests/test_loop.py b/tests/test_loop.py index 24c979ebd55..914b8f1fc4d 100644 --- a/tests/test_loop.py +++ b/tests/test_loop.py @@ -5,7 +5,7 @@ import pytest from aiohttp import web -from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop +from aiohttp.test_utils import AioHTTPTestCase @pytest.mark.skipif( @@ -31,7 +31,6 @@ async def get_application(self): async def on_startup_hook(self, app): self.on_startup_called = True - @unittest_run_loop async def test_on_startup_hook(self) -> None: self.assertTrue(self.on_startup_called) diff --git a/tests/test_test_utils.py b/tests/test_test_utils.py index c268e71073f..d393834927f 100644 --- a/tests/test_test_utils.py +++ b/tests/test_test_utils.py @@ -102,7 +102,6 @@ class TestAioHTTPTestCase(AioHTTPTestCase): def get_app(self): return _create_example_app() - @unittest_run_loop async def test_example_with_loop(self) -> None: request = await self.client.request("GET", "/") assert request.status == 200 @@ -134,6 +133,17 @@ async def test_get_route() -> None: await test_get_route() +def test_unittest_run_loop() -> None: + with pytest.warns( + DeprecationWarning, + match=r"Decorator `@unittest_run_loop` is no longer needed in aiohttp 3\.8\+", + ): + + @unittest_run_loop + def foo(): + pass + + def test_get_route(loop, test_client) -> None: async def test_get_route() -> None: resp = await test_client.request("GET", "/")