I did a simple test case:
def setUp(self): self.testListNone = None def testListSlicing(self): self.assertRaises(TypeError, self.testListNone[:1]) and I am expecting test to pass, but I am getting exception:
Traceback (most recent call last): self.assertRaises(TypeError, self.testListNone[:1]) TypeError: 'NoneType' object is unsubscriptable I thought that assertRaises will pass since TypeError exception will be raised?
14 Answers
If you are using python2.7 or above you can use the ability of assertRaises to be use as a context manager and do:
with self.assertRaises(TypeError): self.testListNone[:1] If you are using python2.6 another way beside the one given until now is to use unittest2 which is a back port of unittest new feature to python2.6, and you can make it work using the code above.
N.B: I'm a big fan of the new feature (SkipTest, test discovery ...) of unittest so I intend to use unittest2 as much as I can. I advise to do the same because there is a lot more than what unittest come with in python2.6 <.
2The problem is the TypeError gets raised 'before' assertRaises gets called since the arguments to assertRaises need to be evaluated before the method can be called. You need to pass a lambda expression like:
self.assertRaises(TypeError, lambda: self.testListNone[:1]) 3The usual way to use assertRaises is to call a function:
self.assertRaises(TypeError, test_function, args) to test that the function call test_function(args) raises a TypeError.
The problem with self.testListNone[:1] is that Python evaluates the expression immediately, before the assertRaises method is called. The whole reason why test_function and args is passed as separate arguments to self.assertRaises is to allow assertRaises to call test_function(args) from within a try...except block, allowing assertRaises to catch the exception.
Since you've defined self.testListNone = None, and you need a function to call, you might use operator.itemgetter like this:
import operator self.assertRaises(TypeError, operator.itemgetter, (self.testListNone,slice(None,1))) since
operator.itemgetter(self.testListNone,slice(None,1)) is a long-winded way of saying self.testListNone[:1], but which separates the function (operator.itemgetter) from the arguments.
Complete snippet would look like the following. It expands @mouad's answer to asserting on error's message (or generally str representation of its args), which may be useful.
from unittest import TestCase class TestNoneTypeError(TestCase): def setUp(self): self.testListNone = None def testListSlicing(self): with self.assertRaises(TypeError) as ctx: self.testListNone[:1] self.assertEqual("'NoneType' object is not subscriptable", str(ctx.exception)) 0