Python 如何编写分两个阶段运行的pytest测试,每个阶段按顺序运行?

Python 如何编写分两个阶段运行的pytest测试,每个阶段按顺序运行?,python,pytest,Python,Pytest,我正在用pytest编写一系列测试,其中许多采用以下形式(伪代码): 事件在UI中出现需要几分钟时间,因此等待\u事件\u在\u UI中出现\u轮询UI中的事件,并超时。这是可行的,但是每次这样的测试都会运行几分钟,所以总的运行时间会很长 因此,我想先运行所有的do\u thingX操作,然后运行所有的验证。我考虑将预期的事件添加到一些列表中,并进行最终测试来验证所有事件——但这意味着如果do_thing1,pytest不会将test1报告为失败,而是将最终测试报告为次优 理想情况下,测试将类似

我正在用pytest编写一系列测试,其中许多采用以下形式(伪代码):

事件在UI中出现需要几分钟时间,因此
等待\u事件\u在\u UI中出现\u
轮询UI中的事件,并超时。这是可行的,但是每次这样的测试都会运行几分钟,所以总的运行时间会很长

因此,我想先运行所有的
do\u thingX
操作,然后运行所有的验证。我考虑将预期的事件添加到一些列表中,并进行最终测试来验证所有事件——但这意味着如果
do_thing1
,pytest不会将
test1
报告为失败,而是将最终测试报告为次优

理想情况下,测试将类似于:

def test1(self, ...):
    expected_events = do_thing1_that_should_generate_events(...)
    # some kind of magic that works like yield?
    assert wait_for_events_to_appear_in_ui(expected_events)
如何实现这一点?

首先看一看,它是用于在多个进程之间并行测试的。我不知道这对你的案子有多有效。请继续阅读,了解更具体的解决方案


您需要在单个测试函数中管理这些测试的异步运行,这是您在问题中暗示的。也许你使用同步代码,也许你使用异步框架;这是正交的。我将假设您可以自己管理这个,并且在任何情况下,它都不是pytest特定的东西

为了解决one-pytest测试函数中的总体通过/失败问题,需要进行子测试。通过提供
subtests
fixture(它还支持
subTest()
from
unittest
),允许您在单个测试函数中编写子测试

下面是提供的示例:

def测试(子测试):
对于范围(5)中的i:
使用subtests.test(msg=“custom message”,i=i):
断言i%2==0
pytest的输出:

λ pytest .tmp\test-subtest.py
======================== test session starts ========================
...
collected 1 item

.tmp\test-subtest.py .F.F..                                    [100%]

============================= FAILURES ==============================
____________________ test [custom message] (i=1) ____________________

    def test(subtests):
        for i in range(5):
            with subtests.test(msg='custom message', i=i):
>               assert i % 2 == 0
E               assert (1 % 2) == 0

.tmp\test-subtest.py:4: AssertionError
____________________ test [custom message] (i=3) ____________________

    def test(subtests):
        for i in range(5):
            with subtests.test(msg='custom message', i=i):
>               assert i % 2 == 0
E               assert (3 % 2) == 0

.tmp\test-subtest.py:4: AssertionError
================ 2 failed, 1 passed in 0.07 seconds =================

失败/通过的数字乍一看有点违反直觉。看起来我们有五个子测验,其中两个应该不及格;事实上,我们报告了两次失败。但我们只有一次通过测试,而不是三次。一次通过是
test_func()
本身;由于
with
块正在捕获内部的断言,
test_func()
没有失败。其他三个子测验没有失败,因此根本没有被报告——尽管我们确实在进度点中看到了它们


总而言之:自己管理测试,并使用来获得失败的单独报告。

您正在调用的
do\u thingx
函数中发生了什么?是什么导致他们花了这么长时间?他们是否在向其他职能部门发出呼吁?或者与数据库或Web服务等外部事物进行通信?
do_thingx
旨在触发测试产品,这就是它的工作原理-它将事件发送到云存储,这需要一些时间来处理,直到它们出现在云UI中,我在那里查找它们。我知道我可以考虑一些可测试性挂钩来缩短这一点,但这项测试旨在进行端到端测试,包括云部分。这正是我想知道的,如果这是功能测试、集成测试或端到端测试。您可能想看看pytest并行。我从未使用过它,但它似乎建议它可以并行运行测试,而不是按顺序运行。谢谢,如果它工作正常,我将尝试并接受它!“其他三个子测验没有失败,因此根本没有被报告”——听起来很糟糕。在
pytest子测试中有任何方法可以绕过它吗?这是一个已知的问题;据介绍,维护人员正在等待pytest中的一些功能来实现这一点。但是,为什么您觉得这很糟糕@Jonathan,因为我希望在两次运行之间测试结果的数量保持不变。如果我有5个(子)测试,我希望看到5个结果(示例中2个失败+3个成功),再加上一个额外的外部测试结果。我不希望结果的数量在两次运行之间发生变化。但我想在它修好之前我必须忍受它。
λ pytest .tmp\test-subtest.py
======================== test session starts ========================
...
collected 1 item

.tmp\test-subtest.py .F.F..                                    [100%]

============================= FAILURES ==============================
____________________ test [custom message] (i=1) ____________________

    def test(subtests):
        for i in range(5):
            with subtests.test(msg='custom message', i=i):
>               assert i % 2 == 0
E               assert (1 % 2) == 0

.tmp\test-subtest.py:4: AssertionError
____________________ test [custom message] (i=3) ____________________

    def test(subtests):
        for i in range(5):
            with subtests.test(msg='custom message', i=i):
>               assert i % 2 == 0
E               assert (3 % 2) == 0

.tmp\test-subtest.py:4: AssertionError
================ 2 failed, 1 passed in 0.07 seconds =================