我一直在使用
unittest.IsolatedAsyncioTestCase
来测试我的异步方法。我一直在使用 setUpClass
、asyncSetUp
来创建固定装置,并使用 asyncTearDown
来进行清理。到目前为止一切进展顺利:-)
但是现在我有一个新的要求,即为每个测试类异步创建一些固定装置,并在整个测试方法中使用它。
我知道
setUpClass
每个测试类运行一次,setUp
每个测试方法运行一次。
asyncSetUp
是 setUp
的异步等价物。但我似乎没有找到 setUpClass
的异步等价物。
那么,每次测试异步创建和清理夹具的最佳方法是什么?
我尝试了官方的单元测试文档https://docs.python.org/3/library/unittest.html#unittest.TestCase.setUpClass,但它只记录了关于
asyncSetUp
。
我使用的是 Python 3.10 并使用 pytest。
没有开箱即用的方法
asyncSetUpClass
,但您可以使用几种解决方案:
from unittest import IsolatedAsyncioTestCase
class TestsContext():
def __init__(self) -> None:
self.init_done: bool = False
async def set_up(self):
if self.init_done:
return
# DO INITIALIZATION HERE
self.init_done = True
class MyServiceTests(IsolatedAsyncioTestCase):
context: TestsContext = TestsContext()
async def asyncSetUp(self):
await self.context.set_up()
async def test_send_request(self):
# test implementation
import asyncio
import threading
from typing import Awaitable
from unittest import IsolatedAsyncioTestCase
def run_in_new_event_loop(worker: Awaitable, *args, **kwargs):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
thread = threading.current_thread()
print(f'Thread {thread.ident}/{thread.name} for {worker}')
return loop.run_until_complete(worker(*args, **kwargs))
finally:
if not loop.is_closed():
loop.close()
class TestsContext():
async def set_up(self):
# DO SETUP HERE
async def tear_down(self):
# DO TEAR DOWN HERE
class MyServiceTests(IsolatedAsyncioTestCase):
context: TestsContext = TestsContext()
@staticmethod
def setUpClass():
run_in_new_event_loop(MyServiceTests.context.set_up)
@staticmethod
def tearDownClass():
run_in_new_event_loop(MyServiceTests.context.tear_down)