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

是否存在在上下文管理器__exit__前执行的pytest异常处理钩子?

解决方案:在上下文管理器__exit__前捕获异常并截图

好问题!我之前做自动化测试时也碰到过一模一样的场景——用上下文管理器管理会话(比如浏览器会话),想在测试崩掉时先截图再让会话自动关闭,试了pytest_runtest_teardown和pytest_runtest_makereport确实都太晚了,它们都是在上下文退出后才触发的。给你分享几个靠谱的解决思路:

1. 在Fixture里包裹会话(最推荐)

如果你的会话是通过pytest Fixture提供的,直接在Fixture的try-except块里处理异常就行,这是最贴合pytest生态的方式:

import pytest
from your_session_module import YourSession

@pytest.fixture(scope="function")
def test_session():
    session = YourSession()
    try:
        yield session  # 这里把会话交给测试用例
    except Exception:
        # 测试抛出异常时,先执行截图,此时会话还没关闭
        take_screenshot(session)
        raise  # 必须重新抛出异常,不然pytest会误以为测试通过
    finally:
        # 不管有没有异常,最后关闭会话(等价于上下文管理器的__exit__逻辑)
        session.close()

测试用例里直接调用这个fixture即可,异常发生时,截图逻辑会在会话关闭前优先执行。

2. 自定义上下文管理器包装原会话

如果你的测试是直接用with语句创建会话,那可以自己写一个上下文管理器把原会话包起来,把截图逻辑嵌入进去:

from contextlib import contextmanager
from your_session_module import YourSession

@contextmanager
def session_with_screenshot():
    session = YourSession()
    try:
        yield session
    except Exception:
        take_screenshot(session)
        raise  # 不要吞掉异常,让pytest正常捕获并标记测试失败
    finally:
        session.close()

测试里替换成如下写法即可:

def test_something():
    with session_with_screenshot() as session:
        # 执行测试逻辑
        session.do_something()

这样异常触发时,会先执行截图操作,再进入finally块关闭会话,完全符合你的需求。

3. 用底层钩子pytest_runtest_protocol(谨慎使用)

这个钩子是pytest执行测试用例的最外层入口,时机非常早,但因为太底层,容易和pytest的其他功能(比如参数化、fixture依赖)冲突,只推荐在特殊场景下尝试:

def pytest_runtest_protocol(item, nextitem):
    try:
        # 执行测试用例的全流程(包括fixture初始化、测试执行)
        item.runtest()
    except Exception:
        take_screenshot()
        raise
    return True  # 告诉pytest我们已自行处理测试执行流程

这个方式的局限性在于,如果你的会话是通过fixture创建的,item.runtest()已经包含了fixture的teardown逻辑,所以可能还是要结合fixture的方式配合使用,不如前两种方案直接稳妥。

总的来说,前两种方式更实用,尤其是Fixture的方案,既能享受到pytest的fixture生命周期管理,又能完美控制截图时机。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:54:19