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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1274047/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 21:50:09  来源:igfitidea点击:

Why isn't assertRaises catching my Attribute Error using python unittest?

pythondjangounit-testing

提问by Jeff

I'm trying to run this test: self.assertRaises(AttributeError, branch[0].childrennodes), and branch[0] does not have an attribute childrennodes, so it should be throwing an AttributeError, which the assertRaisesshould catch, but when I run the test, the test fails because it is throwing an AttributeError.

我正在尝试运行此测试:self.assertRaises(AttributeError, branch[0].childrennodes), 和branch[0] 没有属性childrennodes,因此它应该抛出一个AttributeErrorassertRaises应该捕获它,但是当我运行测试时,测试失败,因为它抛出了一个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'

Any ideas?

有任何想法吗?

采纳答案by David Raznick

I think its because assert raises only accepts a callable. It evalutes to see if the callable raises an exception, not if the statement itself does.

我认为这是因为 assert raise 只接受一个可调用的。它评估可调用对象是否引发异常,而不是语句本身是否引发异常。

self.assertRaises(AttributeError, getattr, branch[0], "childrennodes")

should work.

应该管用。

EDIT:

编辑:

As THC4k correctly says it gathers the statements at collection time and will error then, not at testing time.

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

Also this is a reason why I like nose, it has a decorator (raises) that is useful and clearer for these kind of tests.

这也是我喜欢鼻子的一个原因,它有一个装饰器(加注),对这类测试有用且更清晰。

@raises(AttributeError)
def test_1(self)
    branch[0].childrennodes

回答by Jonathan Hartley

When the test is running, before calling self.assertRaises, Python needs to find the value of all the method's arguments. In doing so, it evaluates branch[0].children_nodes, which raises an AttributeError. Since we haven't invoked assertRaises yet, this exception is not caught, causing the test to fail.

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

The solution is to wrap branch[0].children_nodesin a function or a lambda:

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

self.assertRaises(AttributeError, lambda: branch[0].children_nodes)

assertRaises can also be used as a context manager (Since Python 2.7, or in PyPI package 'unittest2'):

assertRaises 也可以用作上下文管理器(自 Python 2.7 起,或在 PyPI 包“unittest2”中):

with self.assertRaises(AttributeError):
    branch[0].children_nodes
    # etc

This is nice because it can be used on arbitrary blocks of code in the middle of a test, rather than having to create a new function just to define the block of code to which it applies.

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

It can give you access to the raised exception for further processing, if needed:

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

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

self.assertEquals(cm.exception.special_attribute, 123)

回答by Jonathan Hartley

pytest also has a similar decorator:

pytest 也有一个类似的装饰器:

from pytest import raises

def test_raising():
    with raises(AttributeError):
        branch[0].childrennodes