Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unittest asyncio TestCase #4700

Closed
WisdomPill opened this issue Apr 19, 2020 · 1 comment
Closed

unittest asyncio TestCase #4700

WisdomPill opened this issue Apr 19, 2020 · 1 comment

Comments

@WisdomPill
Copy link
Member

🐣 Is your feature request related to a problem? Please describe.

As discussed in #4695 python 3.8 (that this library just started supporting) introduced test cases asyncio capable, for versions below 3.8 there is a library asynctest that is almost equal to what has been introduced in python 3.8. This would make the decorator unittest_run_loop useless and make it simpler to write async test cases.

💡 Describe the solution you'd like

As shown in the PR #4697 asynctest is useful for people using python below 3.8 for patching but for the testcase and mock as well. I tried to include this library in case python below 3.8 and IsolatedAsyncioTestCase and here is an example of what should change in test_utils.

if PY_38:
    from unittest import IsolatedAsyncioTestCase as TestCase
else:
    from asynctest import TestCase  # type: ignore

class AioHTTPTestCase(TestCase):
    """A base class to allow for unittest web applications using
    aiohttp.

    Provides the following:

    * self.client (aiohttp.test_utils.TestClient): an aiohttp test client.
    * self.loop (asyncio.BaseEventLoop): the event loop in which the
        application and server are running.
    * self.app (aiohttp.web.Application): the application returned by
        self.get_application()

    Note that the TestClient's methods are asynchronous: you have to
    execute function on the test client using asynchronous methods.
    """

    async def get_application(self) -> Application:
        """
        This method should be overridden
        to return the aiohttp.web.Application
        object to test.

        """
        return self.get_app()

    def get_app(self) -> Application:
        """Obsolete method used to constructing web application.

        Use .get_application() coroutine instead

        """
        raise RuntimeError("Did you forget to define get_application()?")

    def setUp(self) -> None:
        if PY_38:
            self.loop = asyncio.get_event_loop()

        self.loop.run_until_complete(self.setUpAsync())

    async def setUpAsync(self) -> None:
        self.app = await self.get_application()
        self.server = await self.get_server(self.app)
        self.client = await self.get_client(self.server)

        await self.client.start_server()

    def tearDown(self) -> None:
        self.loop.run_until_complete(self.tearDownAsync())

    async def tearDownAsync(self) -> None:
        await self.client.close()

    async def get_server(self, app: Application) -> TestServer:
        """Return a TestServer instance."""
        return TestServer(app)

    async def get_client(self, server: TestServer) -> TestClient:
        """Return a TestClient instance."""
        return TestClient(server)

I choose this approach to make it backward compatible, in fact all the tests are passing but I am afraid that make_mocked_coroutine should get the same treatment although I did not change it since I saw that it is widely used in many tests. By the way in asynctest and python3.8 there is AsyncMock that should do the trick.

Describe alternatives you've considered

An alternative would break backwards compatibility, actually setUpAsync and tearDownAsync as modified above could break things as well. Another thing that could break things is that the loop in IsolatedAsyncioTestCase has another name, so I added the check for python version in setUp method.

📋 Additional context

I already have a PR available, with this changes and requirements changes to use asynctest with python below 3.8 only. I still have to take on the docs, I am waiting to see how this discussion goes to start and remove unittest_run_loop decorator

@asvetlov
Copy link
Member

Fixed by #4732

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants