Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

assertRaises in unittest not catching Exception properly

I have a file testtest.py that i contains the code

import unittest

def add(self, a, b):
    return a + b

class Test(unittest.TestCase):

    def test_additon(self):
        self.assertRaises(TypeError, add, 1 + '1', msg="Additon failed")
        #self.assertRaises(TypeError, lambda: add(1 + '1'), msg="Addition failed")

if __name__ == '__main__':
    unittest.main()

The problem is that assertRaises doesn't catch the exception properly and all my tests keep failing as errors not based on the condition, this is the output that I'm getting:

E
======================================================================
ERROR: test_additon (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "testtest.py", line 9, in test_additon
    self.assertRaises(TypeError, add, 1 + '1', msg="Additon failed")
TypeError: unsupported operand type(s) for +: 'int' and 'str'

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)

I know i can get around it by using lambda (i commented it out in the code) to make my tests properly catch the exceptions, but according to the docs, passing a callable and the arguments to assertRaises should work, as it will call the function internally by itself and be able to trap any exception that was raised.

assertRaises(*callable*, *args*, *kwargs*)

but it doesn't

if i run it with lambda which is a callable that would be evaluated later by assertRaises, it works as expected and i get this

----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

I'm running python 3.5

Python 3.5.2 (default, Jun 28 2016, 08:46:01) 
[GCC 6.1.1 20160602] on linux

but i also get the same behaviour with python2.7

like image 418
danidee Avatar asked Sep 12 '16 10:09

danidee


People also ask

How do you assert exceptions in Unittest Python?

There are two ways you can use assertRaises: using keyword arguments. Just pass the exception, the callable function and the parameters of the callable function as keyword arguments that will elicit the exception. Make a function call that should raise the exception with a context.

Is Pytest compatible with Unittest?

pytest supports running Python unittest -based tests out of the box. It's meant for leveraging existing unittest -based test suites to use pytest as a test runner and also allow to incrementally adapt the test suite to take full advantage of pytest's features.

Why Pytest is better than Unittest?

Pytest has rich inbuilt features which require less piece of code compared to unittest. In the case of unittest, we have to import a module, create a class and then define testing functions inside the class. But in the case of pytest, we have to define the functions and assert the conditions inside them.

How do you check exceptions in Python?

In Python, exceptions can be handled using a try statement. The critical operation which can raise an exception is placed inside the try clause. The code that handles the exceptions is written in the except clause. We can thus choose what operations to perform once we have caught the exception.


2 Answers

You should be passing arguments to the callable separately, as separate arguments:

self.assertRaises(TypeError, add, 1, '1', msg="Additon failed")
like image 154
alecxe Avatar answered Sep 29 '22 16:09

alecxe


Try

def test_additon(self):
    with self.assertRaises(TypeError):
        add(1 + '1')

The problem is that the exception is raised during argument evaluation before self.assertRaises can kick in.

like image 42
sas Avatar answered Sep 29 '22 17:09

sas