Python UnitTest: AssertRaises pitfall
Saturday, January 14th, 2012
I ran into a little pitfall with Python’s UnitTest module. I was trying to unit test some failure cases where the code I called should raise an exception.
Here’s what I did:
def test_file_error(self): self.assertRaises(IOError, file('/foo', 'r'))
I mistakenly thought this would work, in that assertRaises would notice the IOError exception and mark the test as passed. Naturally, it doesn’t:
ERROR: test_file_error (__main__.SomeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "./test.py", line 10, in test_file_error self.assertRaises(IOError, file('/foo', 'r')) IOError: [Errno 2] No such file or directory: '/foo'
The problem is that I’m a dumbass and I didn’t read the documentation carefully enough:
assertRaises(exception, callable, *args, **kwds)
Test that an exception is raised when callable is called with any positional or keyword arguments that are also passed to assertRaises().
If you look carefully, you’ll notice that I did not pass in a callable. Instead, I passed in the result of a callable! Here’s the correct code:
def test_file_error(self): self.assertRaises(IOError, file, '/foo', 'r')
The difference is that this time I pass a callable (file) and the arguments ('/foo' and 'r') that the test case should pass to that callable. self.AssertRaises will then call it for me with the specified arguments and catch the IOError. In the first scenario (the wrong code), the call is made before the unit test is actually watching out for it.