Each Answer to this Q is separated by one/two green lines.
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
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 <.
The 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])
The 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
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)))
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))