3

This is in Python 2.7. I have a class called class A, and there are some attributes that I want to throw an exception when being set by the user:

myA = A()
myA.myattribute = 9   # this should throw an error

I want to write a unittest that ensures that this throws an error.

After creating a test class and inheriting unittest.TestCase, I tried to write a test like this:

myA = A()
self.assertRaises(AttributeError, eval('myA.myattribute = 9'))

But, this throws a syntax error. However, if I try eval('myA.myattribute = 9'), it throws the attribute error, as it should.

How do I write a unittest to test this correctly?

Thanks.

1
  • See my answer here for the proper unittest syntax. Commented Mar 22 at 16:02

2 Answers 2

5

You can also use assertRaises as a context manager:

with self.assertRaises(AttributeError):
    myA.myattribute = 9

The documentation shows more examples for this if you are interested. The documentation for assertRaises has a lot more detail on this subject as well.

From that documentation:

If only the exception and possibly the msg arguments are given, return a context manager so that the code under test can be written inline rather than as a function:

with self.assertRaises(SomeException):
     do_something()

which is exactly what you are trying to do.

Sign up to request clarification or add additional context in comments.

Comments

2

self.assertRaises takes a callable (and optionally one or more arguments for that callable) as its argument; you are providing the value that results from calling the callable with its arguments. The correct test would be self.assertRaises(AttributeError, eval, 'myA.myattribute = 9')

# Thanks to @mgilson for something that actually works while
# resembling the original attempt.
self.assertRaises(AttributeError, eval, 'myA.myattribute = 9', locals())

However, you should use assertRaises as a context manager, which allows you to write the much more natural

with self.assertRaises(AttributeError):
    myA.myattribute = 9

2 Comments

Would that first form work? eval will evaluate the expression in the current namespace -- which is the namespace in which eval is getting called which would not have myA defined. If you're going to use the functional form (which isn't advised), you probably should go with self.assertRaises(AttributeError, setattr, myA, 'myattribute', 9), or you'll have to pass the current function's locals through: self.assertRaises(AttributeError, eval, 'myA.myattribute = 9', locals())
Yeah, I didn't really give any thought to how you would correctly use eval. I should have just explained that assertRaises takes something that it can call, rather than the result of a expression, and left it at that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.