pytest 固定装置按啥顺序执行?

Posted

技术标签:

【中文标题】pytest 固定装置按啥顺序执行?【英文标题】:In which order are pytest fixtures executed?pytest 固定装置按什么顺序执行? 【发布时间】:2014-10-28 21:12:14 【问题描述】:

对于我正在测试的应用程序,我想创建一个 autouse=True 固定装置,如果 smtplib.SMTP.connect 尝试意外发送电子邮件,该固定装置会导致测试失败。

但是,在我确实希望测试发送电子邮件的情况下,我想使用不同的装置来记录这些电子邮件(很可能通过使用来自 pytest-localserversmtpserver 装置和猴子修补 connect 方法来使用该夹具返回的主机/端口)

当然,只有在 autouse 固定装置在另一个固定装置(作为 funcarg 加载)之前执行时才有效。是否有任何特定的夹​​具执行顺序和/或有办法保证执行顺序?

【问题讨论】:

一个非常有道理的问题,我已经看到灯具被滥用了很多次,最成问题的事情之一是哪个灯具在哪个之前运行 另一个有用的技巧是,fixture 可以检查测试函数的 pytest 标记。这意味着您可以@mark 需要执行特殊操作的测试,然后使用请求对象检查测试函数是否有标记。如果是,请在您的灯具中执行不同的操作。 知道拆解顺序也不错 【参考方案1】:

控制夹具执行顺序的最简单方法是在后一个夹具中请求前一个夹具。所以要确保ba 之前运行:

@pytest.fixture(autouse=True, scope="function")
def b():
    pass

@pytest.fixture(scope="function")
def a(b):
    pass

有关一般夹具分辨率顺序的详细信息,请参阅Maxim's excellent answer below 或查看the documentation。

【讨论】:

似乎不适用于 pytest 3.0.2(无自动使用)。尝试将 capfd 与另一个夹具一起使用,该夹具创建一个将 sys.stdout 保存到变量的类:避免夹具捕获输出,尝试强制 capfd 像这样首先设置。 pytest 3.0.2 和“无自动使用”是什么意思?这段代码在 pytest 3.0.2 和 3.0.3(最新)中对我来说很好。 我看到这个订单失败的大部分时间是因为我的一个装置由于错误而没有完成,请仔细查看设置错误【参考方案2】:

我只是在使用两个 function-scoped 自动使用装置时遇到了这个问题。我希望夹具 b 在夹具 a 之前运行,但每次,a 先运行。我想也许它是按字母顺序排列的,所以我将a 重命名为c,现在b 先运行。 Pytest 似乎没有记录这一点。这只是一个幸运的猜测。 :-)

这是用于自动使用的装置。考虑到更广泛的范围(例如modulesession),当 pytest 遇到需要它的测试时会执行一个fixture。因此,如果有两个测试,并且第一个测试使用名为 sbsession 范围的夹具,而不是名为 sa 的夹具,那么 sb 将首先执行。当下一个测试运行时,它将启动sa,假设它需要sa

【讨论】:

可以确认 py.test 版本 2.6.4。 我也在使用 2.6.4。【参考方案3】:

TL;DR

在构建夹具评估顺序时会同时考虑 3 个方面,方面本身按优先级排列:

Fixture 依赖项 - 从 rootest required 评估fixture 到一个在测试函数中需要夹具范围 - 从sessionmodulefunction 范围内评估夹具。在同一范围内,autouse 固定装置在非自动使用的固定装置之前进行评估。 测试函数参数中的夹具位置 - 按照测试函数参数中存在的顺序评估夹具,从最左最右

以下链接的代码示例的官方解释

https://docs.pytest.org/en/stable/fixture.html#fixture-instantiation-order

【讨论】:

第三点“存在顺序......从左到右”没有得到 pytest 文档的证实。来自docs.pytest.org/en/stable/fixture.html#fixture-order:“. . . . . . . . . 所要求的订单夹具与巧合后的执行订单无关”【参考方案4】:

IIRC 您可以依赖更高范围的固定装置首先执行。因此,如果您为monkeypatch smtplib.SMTP.connect 创建了一个会话范围的自动使用fixture,那么您可以创建一个函数范围的fixture,它为一个测试撤消这个monkeypatching,然后恢复它。我认为最简单的方法是创建你自己的smtpserver 夹具,它依赖于disallow_smtp 夹具以及来自pytest-localserversmtpserver 夹具,然后处理使这两个工作所需的所有设置和拆卸在一起。

这是pytest-django 处理它的数据库访问的模糊方式顺便说一句,您可以尝试查看那里的代码,但它远非一个简单的示例,并且有许多自己奇怪的东西。

【讨论】:

【参考方案5】:

借助以下代码,我们可以轻松设置夹具/功能的执行顺序

例如:-

执行顺序优先

@pytest.mark.order(1)

执行顺序秒

@pytest.mark.order(2)

【讨论】:

这个解决方案可能是指一个名为 pytest-ordering 的外部 pytest 插件,而不是 pytest 本身。

以上是关于pytest 固定装置按啥顺序执行?的主要内容,如果未能解决你的问题,请参考以下文章

pytest 固定装置从外部范围重新定义名称 [pylint]

pytest 固定装置在一个单独的目录中

pytest 如何以及在哪里找到固定装置

4.pytest中固定装置setup和teardown

『德不孤』Pytest框架 — 4.pytest.ini文件和用例执行的顺序

pytest文档34-Hooks函数改变用例执行顺序(pytest_collection_modifyitems)