首页 > 解决方案 > 在重新运行测试时防止过早的会话夹具拆卸

问题描述

我在 conftest.py 中设置了一些配置,以便在特定情况下重新运行失败的 pytest 测试。

此功能已添加到 conftest.py。这个想法是,可以通过使用请求夹具将 request.node.retry 设置为 True 来将测试设置为重试。

def pytest_runtest_protocol(item, nextitem):
"""Checks for manual mark and if found, reruns test if requested"""
if item.get_closest_marker("manual") is None:
    return

# Infinite loop for rerunning tests
while True:
    # Run test and get result
    item.ihook.pytest_runtest_logstart(
        nodeid=item.nodeid,
        location=item.location
    )

    # Hangs on this line on retry
    reports = runtestprotocol(item, nextitem=nextitem)

    # Check results
    if not getattr(item, 'retry', False):
        for report in reports:
            item.ihook.pytest_runtest_logreport(report=report)
        return True
    else:
        delattr(item, 'retry')

这在运行多个测试时有效,但如果只运行一个测试,或者测试是系列中的最后一个,那么测试的第一次失败会导致所有夹具的拆除。功能级别的fixture可以重新设置(实际上,我希望它们能够确保干净的状态)但是会话级别的fixture也被拆除了,我需要它们重新开始测试。

在我准备好之前,有什么方法可以防止会话级别的夹具拆卸?

标签: pythonpytest

解决方案


对此的解决方案有点破解 - 它添加了一个不会被记录的虚拟测试。

安装 pytest-ordering。在标记为最后的地方添加一个带有虚拟测试的新文件,例如

@pytest.mark.last
def test_dummy():
    assert True

然后在 pytest_runtest_protocol 函数中,一开始就跳过虚拟测试:

def pytest_runtest_protocol(item, nextitem):
    if item.name == 'test_dummy':
        return False
    # Rest of function

由于最后一个函数将始终是无法重试的虚拟函数,因此会话夹具在进入测试时将是有效的,并且只会在之后被拆除。


推荐阅读