Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 assertRaises should catch, but when I run the test, the test fails because it is throwing an 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?

like image 268
Jeff Avatar asked Sep 10 '25 15:09

Jeff


1 Answers

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.

The solution is to wrap branch[0].children_nodes in a function or a 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'):

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)
like image 176
Jonathan Hartley Avatar answered Sep 12 '25 08:09

Jonathan Hartley