Sahand
Sahand

Reputation: 8360

Python Unittest - Unintended usage for assertRaises?

I wonder if there is a way to do the following:

class Test_Vector_test(unittest.TestCase):
    def test_add(self):
        vector1 = Vector(2,2,2)
        scalar = 1
        self.assertRaises(NotImplementedError, vector1+scalar)

This test is failed with the following error code:

Traceback (most recent call last):
  File "/Users/sahandz/Documents/School/Programmeringsteknik och Matlab/dd1315pylab3-master/test/test_Vector.py", line 14, in test_add
    self.assertRaises(NotImplementedError, vector1+scalar)
  File "/Users/sahandz/Documents/School/Programmeringsteknik och Matlab/dd1315pylab3-master/lab/Vector.py", line 17, in __add__
    raise NotImplementedError
NotImplementedError

----------------------------------------------------------------------
Ran 3 tests in 0.007s

FAILED (errors=1)

even though you can see that it actually raises the error. How can I reach the desired functionality (checking if vector1+scalar raises NotImplementedError) without using the vector1.__add__ method?

Upvotes: 1

Views: 2240

Answers (5)

Sahand
Sahand

Reputation: 8360

Thanks for your solutions guys. I think the lambda solution was definitely the easiest and most intuitive.

Before getting your answers, here's what I came up with myself:

    try: 
        vector1+scalar
        result = False
    except NotImplementedError:
        result = True
    self.assertTrue(result, msg="Vector+scalar did not cause the wanted error.")

The functionality is the same, but some additional lines are required.

Upvotes: 1

user5547025
user5547025

Reputation:

See the documentation of assertRaises:

Test that an exception is raised when callable is called with any positional or keyword arguments that are also passed to assertRaises().

vector1+scalar is not a callable, it is an expression.

Upvotes: 0

chepner
chepner

Reputation: 531165

The problem is that NotImplementedError is raised while the argument is being evaluated, before assertRaises is actually called. Your code is equivalent to

x = vector1 + scalar
self.assertRaises(NotImplementedError, x)

You need to defer the (attempted) call to Vector.__add__.

self.assertRaises(NotImplementedError, vector1.__add__, scalar)

Upvotes: 1

syntonym
syntonym

Reputation: 7384

assertRaises awaits something callable that then will raise the error. vector1+scalar is evaluated before the function assertRaises is even executed. Either use a function, a lambda or with:

with self.assertRaises(SomeException):
    do_something()

See also the documentation.

Upvotes: 6

alpha1554
alpha1554

Reputation: 605

You should use a callable type, not the actual code (which raises the error). The result would be this :

self.assertRaises(NotImplementedError, lambda:vector1+scalar)

Upvotes: 2

Related Questions