How does one write a test that fails only if a function doesn't throw an expected exception?
Have a look at the assertRaises method of the unittest
module.
Use TestCase.assertRaises (or TestCase.FailUnlessRaises) from the unittest module
see here: http://docs.python.org/library/unittest.html#unittest.TestCase.assertRaises
for example:
import mymod
class MyTestCase(unittest.TestCase):
def test1(self):
self.assertRaises(SomeCoolException, mymod.myfunc)
Your code should follow this pattern (this is a unittest module style test):
def test_afunction_throws_exception(self):
try:
afunction()
except ExpectedException:
pass
except e:
self.fail('Unexpected exception thrown:', e)
else:
self.fail('ExpectedException not thrown')
Wow! Questions get answered fast on stackoverflow.com! I'm glad I asked this.
The code in my previous answer can be simplified to:
def test_afunction_throws_exception(self):
self.assertRaises(ExpectedException, afunction)
And if afunction takes arguments, just pass them into assertRaises like this:
def test_afunction_throws_exception(self):
self.assertRaises(ExpectedException, afunction, arg1, arg2)
See also: How do I unit test an init() method of a python class with assertRaises()?
Which presents some code for using the built in python unit testing framework for testing exception raising, beyond what is possible without extending.
I use doctest[1] almost everywhere because I like the fact that I document and test my functions at the same time.
Have a look at this code:
def throw_up(something, gowrong=False):
"""
>>> throw_up('Fish n Chips')
Traceback (most recent call last):
...
Exception: Fish n Chips
>>> throw_up('Fish n Chips', gowrong=True)
'I feel fine!'
"""
if gowrong:
return "I feel fine!"
raise Exception(something)
if __name__ == '__main__':
import doctest
doctest.testmod()
If you put this example in a module and run it from the command line both test cases are evaluated and checked.
[1] Python documentation: 23.2 doctest -- Test interactive Python examples
I just discovered that the Mock library provides an assertRaisesWithMessage() method (in its unittest.TestCase subclass), which will check not only that the expected exception is raised, but also that it is raised with the expected message:
from testcase import TestCase
import mymod
class MyTestCase(TestCase):
def test1(self):
self.assertRaisesWithMessage(SomeCoolException,
'expected message',
mymod.myfunc)
Since Python 2.7 you can use context manager to get a hold of the actual Exception object thrown, which enables you check for various fields in the exception object, like message:
def broken_function():
raise Exception('This is broken')
....
with self.assertRaises(MyException) as context:
broken_function()
self.assertEqual(context.exception.message, 'This is broken')
http://docs.python.org/dev/library/unittest.html#unittest.TestCase.assertRaises
You can use assertRaises from the unittest module
import unittest
class TestClass():
def raises_exception(self):
raise Exception("test")
class MyTestCase(unittest.TestCase):
def test_if_method_raises_correct_exception(self):
test_class = TestClass()
# note that you dont use () when passing the method to assertRaises
self.assertRaises(Exception, test_class.raises_exception)