Tuesday 5 September 2006 — This is 18 years old. Be careful.
I use the standard unittest module for testing, despite the community’s general protestations about it not being pythonic. It does what I need, except for one thing. It has an assertRaises method that tests that a callable raises an exception of the expected class, but the message that comes with the exception is not checked. So I usually mix this method into my test case base class:
def assertRaisesMsg(self, excClass, msg, callableObj, *args, **kwargs):
""" Just like unittest.TestCase.assertRaises,
but checks that the message is right too.
"""
try:
callableObj(*args, **kwargs)
except excClass, exc:
excMsg = str(exc)
if not msg:
# No message provided: any message is fine.
return
elif excMsg == msg:
# Message provided, and we got the right message: it passes.
return
else:
# Message provided, and it didn't match: fail!
raise self.failureException(
"Right exception, wrong message: got '%s' expected '%s'" %
(excMsg, msg)
)
else:
if hasattr(excClass, '__name__'):
excName = excClass.__name__
else:
excName = str(excClass)
raise self.failureException(
"Expected to raise %s, didn't get an exception at all" %
excName
)
I can call it (for example) like this:
self.assertRaisesMsg(MyException, "Exception message", my_function, (arg1, arg2))
This test line will call my_function(arg1, arg2) and succeed if it raises a MyException with the message “Exception message”. It will fail in all other cases.
Comments
We use unittest at work. We've customised it a bit, but it's very easy to add new tests. I think unittest gets more flak than it deserves. :-)
I added an "assertRaisesEx" to the Python Cookbook a while back that adds "(1) the ability to assert the raised exception's args; (2) the ability to test that the stringified exception matches a given regular expression; and (3) much better failure messages."
Cheers
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/307970
I want an AttributeError to have obj and name attributes, so I know what name was not found on what object. I want to see exactly what caused the error without looking at a message, so I can handle it properly.
http://codespeak.net/py/current/doc/test.html#how-to-write-assertions-about-exceptions
Something like:
assert py.test.raises(Exception, func, *args, **kwargs).value.args == msg
>>> import locale
>>> import os
>>> def reallysetlocale(loc):
os.environ['LANG'] = loc
os.environ['LANGUAGE'] = loc
locale.setlocale(locale.LC_ALL, loc)
>>> file("test", "r")
Traceback (most recent call last):
File "", line 1, in ?
IOError: [Errno 2] No such file or directory: 'test'
>>> reallysetlocale('fr_FR.UTF-8')
>>> file("test", "r")
Traceback (most recent call last):
File "", line 1, in ?
IOError: [Errno 2] Aucun fichier ou r������©pertoire de ce type: 'test'
By the way, I don't have an answer to this problem. Personally I've been ignoring internationalization for some time, and I suspect that one day it's going to bite me really hard.
Unfortunately most software ignores more than just that - internationalization and encoding rules. Just look at what this blog software did to my error message! :)
Thanks, everyone! This has been a richer discussion than I anticipated, and has moved on to the next blog post...
Add a comment: