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

pytest测试中异常场景下后续代码未终止执行的原因咨询

问题解析与原因说明

你这段测试代码里,当k=None时,t(k)明明抛出了ValueError,但看起来with块内t(k)之后的if/else代码好像还执行了,而且测试能通过——其实是你对pytest.raises的工作逻辑理解错了。

核心原因:pytest.raises的执行机制

pytest.raises是专门用来捕获并验证异常的上下文管理器,它的流程和普通try/except不一样:

  • 进入with块时,它会准备好捕获指定类型的异常
  • 当块内代码抛出符合要求的异常时,它会把异常对象存到ex.value里,然后告诉Python“这个异常已经处理完了”
  • 但异常发生点之后的代码根本不会执行

你觉得后续代码执行了,其实是误解——当k=None时,kk = t(k)这一行抛出异常后,后面的if/else断言完全没跑,测试能通过只是因为pytest.raises成功捕获到了预期的异常,和你写的else分支断言没关系。

修正你的测试代码

你的测试逻辑有问题,应该把断言放到with块外面,分场景验证:

from contextlib import nullcontext as does_not_raise

import pytest


def t(k):
    if k:
        return k
    else:
        raise ValueError("Value")


@pytest.mark.parametrize("k, cntxt", [(None, pytest.raises(ValueError)), ("Value", does_not_raise())])
def test_t(k, cntxt):
    with cntxt as ex:
        kk = t(k)

    # 把断言移到with块外,确保两种场景都能正确验证
    if k:
        assert kk == k
        assert ex is None
    else:
        assert str(ex.value) == "Value"

这样改了之后:

  • 当k="Value"时,with块正常执行完,kk拿到返回值,后续断言验证结果
  • 当k=None时,with块捕获到异常,ex.value保存了异常信息,后续断言验证异常内容

额外说明:does_not_raise的作用

这个空上下文管理器就是为了让两种测试场景的代码结构统一,不需要写两套逻辑,符合参数化测试的简洁性要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 04:50:18