为什么assertRaises没有使用python unittest捕获我的属性错误?

Jef*_*eff 24 python django unit-testing

我试图运行这个测试:self.assertRaises(AttributeError, branch[0].childrennodes)branch[0]没有属性childrennodes,所以它应该被抛出AttributeError,其中assertRaises应赶上,但是当我运行测试,测试,因为它是抛出一个失败AttributeError.

Traceback (most recent call last):
  File "/home/tttt/../tttt/tests.py", line 504, in test_get_categories_branch
    self.assertRaises(AttributeError, branch[0].children_nodes)
AttributeError: 'Category' object has no attribute 'children_nodes'
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Jon*_*ley 55

当测试运行时,在调用self.assertRaises之前,Python需要找到所有方法参数的值.在这样做时,它会进行求值branch[0].children_nodes,从而引发AttributeError.由于我们尚未调用assertRaises,因此未捕获此异常,导致测试失败.

解决方案是包装branch[0].children_nodes函数或lambda:

self.assertRaises(AttributeError, lambda: branch[0].children_nodes)
Run Code Online (Sandbox Code Playgroud)

assertRaises也可以用作上下文管理器(从Python 2.7开始,或者在PyPI包'unittest2'中):

with self.assertRaises(AttributeError):
    branch[0].children_nodes
    # etc
Run Code Online (Sandbox Code Playgroud)

这很好,因为它可以在测试过程中用于任意代码块,而不必创建一个新函数来定义它应用的代码块.

如果需要,它可以让您访问引发的异常以进行进一步处理:

with self.assertRaises(AttributeError) as cm:
    branch[0].children_nodes

self.assertEquals(cm.exception.special_attribute, 123)
Run Code Online (Sandbox Code Playgroud)

  • lambda超级优雅,感谢发布此:) (3认同)

Dav*_*ick 22

我认为因为断言加注只接受一个可调用的.它评估是否可调用引发异常,而不是语句本身.

self.assertRaises(AttributeError, getattr, branch[0], "childrennodes")
Run Code Online (Sandbox Code Playgroud)

应该管用.

编辑:

正如THC4k正确地说它在收集时收集语句,然后会出错,而不是在测试时.

这也是我喜欢鼻子的原因,它有一个装饰器(加注),对于这类测试来说是有用和清晰的.

@raises(AttributeError)
def test_1(self)
    branch[0].childrennodes
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的解决方案,但是当Python收集`self.assertRaises`的参数时会发生异常.它必须在调用函数之前评估`branch [0] .childrennodes`,它会像预期的那样引发异常. (2认同)