能否通过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
相关产品推荐
相关产品推荐

