如何使用 pytest 的设置作为异步方法?



我有以下代码:

import asyncio
import pytest
from mymodule import myasyncfunction
from unittest import TestCase

class TestDummy(TestCase):
def setUp(self):
await myasyncfunction()
@pytest.mark.asyncio
async def test_dummy(self):
assert False

测试通过,因为它根本不进入测试。它只说:

运行时警告:协程"TestDummy.setUp"从未等待过

如何使设置功能异步?

观察:如果我从 TestCase 中删除继承,测试会运行,但它之前不会进入 setUp 函数,这是必需的。

解决方案是将方法定义为夹具,而不是使用传统的setUp((方法。

import pytest
class TestClass:
@pytest.fixture
def setup(self):
pass
@pytest.mark.asyncio
async def test_some_stuff(setup):
pass

正如你所发现的,使用 pytest-asyncio 时,当类继承自 Unitest.Testcase 时,setUp(( 方法不起作用:

TestPersonClass 不是 unittest 的子类。测试用例。如果是,测试仍将成功 - 但成功将是误报,因为 await 表达式之后的代码不会运行。

为什么会这样?答案足够复杂,值得一个 单独的帖子,但TL;DR 版本是第 93 行的版本 pytest-asyncio 的源代码 作者期望事件循环是 从 pytest 夹具传递到测试中,而单元测试。测试用例 方法不能直接接收夹具函数参数。

有关上述解释,请参阅本博客文章的结尾: https://jacobbridges.github.io/post/unit-testing-with-asyncio/

有关使用 pytest-asyncio 进行测试的一些不错的教程,请参阅: 1(https://www.roguelynn.com/words/asyncio 测试/2(https://medium.com/ideas-at-igenius/testing-asyncio-python-code-with-pytest-a2f3628f82bc

我今天遇到了这个问题。就我而言,使用此模式可以轻松修复:

class TestDummy:
def setup_class(self) -> None:
asyncio.run(do_server_registration_setup_stuff())
# other sync setup logic...
@pytest.mark.asyncio
async def test_some_stuff(setup):
pass

这可能不适合您的需求,但对我来说,我正在进行功能测试,因此只需要使用 aiohttp 运行一些 http POST 请求以在运行测试之前注册帐户设置等......

如果您需要在 TestDummy 实例上预填充一些内存中缓存,您可以将self传递给do_server_registration_setup_stuff并在其中设置实例属性。

可能有更好的方法,但也许这可以帮助某人解决眼前的问题并保持其发展!

最新更新