pytest.raises(错误)如何工作?

时间:2016-01-24 17:42:00

标签: python pytest

新的Python,但我试图理解这段代码:

with pytest.raises(ValueError):
    group_adjust(vals, [grps_1, grps_2], weights)

在阅读this tutorial on with后,我了解pytest.raises()会返回一个上下文管理器,用于设置和清除调用group_adjust()之前和之后的内容。我也理解,如果出现问题,group_adjust()应该提出ValueError

当引发ValueError时,pytest如何“反应”? AFAIK,只有设置和清理所以我不确定它如何捕获异常。最终目标是了解将pytest作为上下文管理器的好处。

3 个答案:

答案 0 :(得分:1)

__exit__魔术函数接受exception_typeexception_valuetraceback参数:

In [5]: class RaisesContext:
   ...:     def __enter__(self):
   ...:         return self
   ...:     def __exit__(self, exception_type, exception_value, traceback):
   ...:         print('Exception type:', exception_type)
   ...:         print('Exception value:', exception_value)
   ...:         print('Traceback:', traceback)
   ...:         return True
   ...:     

In [6]: with RaisesContext():
   ...:     raise ValueError('Something went wrong')
   ...: 
Exception type: <class 'ValueError'>
Exception value: Something went wrong
Traceback: <traceback object at 0x7fd92f4a2c48>

如果None块正常结束,它们为with

In [7]: with RaisesContext():
   ...:     pass
   ...: 
Exception type: None
Exception value: None
Traceback: None

答案 1 :(得分:1)

我不完全确定pytest,但任何上下文管理器在其退出时传递3个参数,exc_type,Excepton和Traceback,如果没有异常,则所有三个都没有,如果退出返回True然后也会抑制异常,

在此更好地解释:https://docs.python.org/2/reference/datamodel.html#object.exit

所以,如果我想创建一个简单的处理程序来显示回溯而不停止程序,我可以这样做:

import traceback
class VerboseTry:
    def __enter__(self):
        pass
    def __exit__(self,exc_type,error,trace):
        if exc_type:
            traceback.print_exception(exc_type,error,trace)
            return True

def f(depth=4):
    """this will (needlessly) raise an error with several iterations to the traceback"""
    if depth==0:
        int("this is going to fail")
    else:
        return f(depth-1)

print("starting")
with VerboseTry():
    f()
print("got to end")

查看在不停止程序的情况下引发的错误。

答案 2 :(得分:1)

with构造调用两个&#34;魔法&#34;方法,__enter____exit__分别位于代码块的开头和结尾。因此,

with foo:
    x = 1

可以理解为:

foo.__enter__()
x = 1
foo.__exit__()

除非在hir回答中提及,__exit__会调用为什么代码块正在退出的详细信息:如果是异常,那么是什么类型,None

因此,pytest.raises(TYPE)返回的对象已配置为期望 TYPE的例外。 __exit__方法将它接收的参数与声明实际(如果有)异常的参数与存储预期异常类型的内部数据成员进行比较,然后决定是否通过测试。