You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过pytest钩子实现失败测试重跑并修正结果?如何调用setup/teardown?

问题描述

我正在开展UI自动化测试,这类测试结果容易不稳定,现在需要做概念验证:能不能通过pytest钩子实现失败测试重跑,如果第二次尝试通过就把测试结果改成'passed'?

目前我已经实现了基础的重跑逻辑,但重跑过程里setup和teardown函数没被调用,请问怎么在重跑时调用这些函数?当前我的pytest钩子代码如下:

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    report = yield
    result = report.get_result()
    if result.outcome == 'failed':
        try:
            # Run the original tests teardown
            # Run the tests setup
            attempt = item.runtest()
            # Run the tests teardown
        except:
            attempt = 'failed'
        if not attempt:
            result.outcome = 'passed'
解决方案

直接调用item.runtest()只会执行测试函数本身,不会触发pytest的setup/teardown生命周期(比如setup_method、teardown_method或者pytest_setup_function这类钩子)。要完整重跑测试流程,需要手动触发测试的三个阶段:setup、测试执行、teardown。

正确的重跑实现代码

修改你的钩子函数,手动调用测试生命周期的各个步骤:

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    report = yield
    result = report.get_result()

    # 仅在测试函数执行阶段失败时触发重跑
    if result.outcome == 'failed' and call.when == 'call':
        # 先清理第一次测试的环境
        if hasattr(item, '_request'):
            item._request._pyfuncitem = item
            item.teardown()

        try:
            # 重新执行setup初始化环境
            item.setup()
            # 执行测试函数
            item.runtest()
            # 清理重跑后的环境
            item.teardown()
            # 重跑成功,修改结果为passed
            result.outcome = 'passed'
        except Exception:
            # 重跑失败,保持原失败结果
            pass

关键说明

  • item.setup():触发测试的完整setup流程,包含类级、方法级的所有setup函数
  • item.teardown():触发测试的完整teardown流程,确保测试环境被彻底清理
  • 先执行teardown再setup:避免第一次失败后的残留环境影响重跑的测试结果
  • 限定call.when == 'call':只针对测试函数本身的失败触发重跑,避免setup/teardown阶段失败时无限循环

内容的提问来源于stack exchange,提问作者Nick H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 14:15:26