I'm using pytest 5.4.3 to run asynchronous unit tests.
Typically I like to run an isolated server instance and perform the unit test cases together with the spinned up server. Currently I'm trying to perform asynchronous unit tests, running a uvicorn server instance.
Anywhere else, I'd use asyncio.gather for running tasks in parallel, but asyncSetUp method forces the use of run_until_complete, as seen in _callAsync implementation in lib/python3.8/unittest/async_case.py:74.
Any long-running task will therefore make the unit test stuck on beginning, until KeyboardInterrupt is raised. The interrupt, indeed, stops the server instance and continues to perform the individual test cases.
Using asyncio.create_task to schedule the coroutine on the loop will on the other hand freezes the process completely and needs to be killed. The code used in this case follows:
class HttpTestCase(IsolatedAsyncioTestCase):
async def asyncSetUp(self):
...
self.task = uvicorn.Server(server_config).serve()
asyncio.create_task(self.task)
I've also noticed that it depends on the implementation of the long-running task. For example, running a aiocoap server instance works perfectly well, because the coroutine will finish after the server start and handles the running in the background itself:
class CoapTestCase(IsolatedAsyncioTestCase):
async def asyncSetUp(self):
...
self.server = await aiocoap.Context.create_server_context(...)
async def asyncTearDown(self):
await self.server.shutdown()
What is the correct way to achieve having long-running tasks in background and continue with unit testing? Running the server in separate thread/process is always an option, but I'd be interested in figuring out how to do this using just asyncio.
Thanks for answers.