pytest中上下文管理器内AssertionError未抛出是什么原因?
异常未抛出的根本原因
这是Python上下文管理器的原生设计规则,不是pytest的bug,不需要提交issue。
Python对__exit__方法的返回值有明确的规定:
- 当
with代码块内部抛出异常时,解释器会将异常类型、异常实例、回溯栈三个参数传入__exit__方法 - 如果
__exit__返回真值,解释器会判定异常已经被处理完成,不会继续向外层抛出异常 - 如果
__exit__返回假值,或者没有显式返回值(默认返回None,属于假值),异常会正常向外传播
你第一个版本的__exit__返回了self(当前类的实例),所有非空的自定义类实例在Python中都属于真值,所以assert False抛出的AssertionError直接被上下文管理器吞掉了,pytest自然捕获不到失败信息。
你把__exit__改为pass后,方法没有显式返回值,默认返回None(假值),异常可以正常向外抛出,pytest就能正常捕获断言失败。
你可以脱离pytest直接运行以下代码验证,就能确认是Python原生行为,和测试框架无关:
class foo: def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): return self if __name__ == "__main__": with foo(): assert False print("程序正常结束,异常被上下文管理器吞噬")
内容的提问来源于stack exchange,提问作者HeyMan
相关产品推荐
相关产品推荐

