Test if a function throws an exception in Python

The unittest unit testing framework is used to validate that the code performs as designed. To achieve this, unittest supports some important methods in an object-oriented way:  

  • test fixture
  • test case
  • test suite
  • test runner

A deeper insight for the above terms can be gained from https://www.geeksforgeeks.org/unit-testing-python-unittest/

assertRaises() – It allows an exception to be encapsulated, meaning that the test can throw an exception without exiting the execution, as is normally the case for unhandled exceptions. The test passes if exception is raised, gives an error if another exception is raised, or fails if no exception is raised.

There are two ways you can use assertRaises:

  1. using keyword arguments.
    assertRaises(exception, function, *args, **keywords)
    

    Just pass the exception, the callable function and the parameters of the callable function as keyword arguments that will elicit the exception.



  2. using context manager 
    assertRaises(exception)
    

    Make a function call that should raise the exception with a context. The context manager will caught an exception and store it in the object in its exception attribute. This is useful when we have to perform additional checks on the exception raised.

We write a unittest that fails if no exception is raised by a function or when an exception raised by assert statement is different from expected exception. Thus, by this method we can check if an exception is raised by a function or not.

Example 1 :

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

import unittest
  
class MyTestCase(unittest.TestCase):
  
   # Returns true if 1 + '1' raises a TypeError
   def test_1(self):
      with self.assertRaises(Exception):
         1 + '1'
  
if __name__ == '__main__'
    unittest.main()

chevron_right


Output : 

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

OK

Here, in the output the “.” on the first line of output means that test has passed and the function has thrown an exception of  TypeError while adding an integer value and a string value.



Example 2 :

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

import unittest
  
class MyTestCase(unittest.TestCase):
  
   # Returns false if 1 + 1 raises no Exception
   def test_1(self):
      with self.assertRaises(Exception):
         1 + 1
  
if __name__ == '__main__'
    unittest.main()

chevron_right


Output : 

F
======================================================================
FAIL: test_1 (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/5bc65171e57a3294596f5333f4b7ed53.py", line 6, in test_1
    1 + 1
AssertionError: Exception not raised

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

Since adding an integer to an integer (in this case 1 + 1)  does not raise any exception, results in the unittest to fail.

Example 3 :



Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

import unittest
  
class MyTestCase(unittest.TestCase):
  
  # Returns true if 100 / 0 raises an Exception
   def test_1(self):
      with self.assertRaises(ZeroDivisionError):
         100 / 0
  
if __name__ == '__main__'
    unittest.main()

chevron_right


Output :

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

OK

Any number divided by 0 gives ZeroDivisionError exception. Therefore, in example 3, when 100 is divided by 0 it raises an Exception of type ZeroDivisionError resulting in unittest to pass. Thus “.” in output signifies that the test has been passed.

Example 4 :

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

import unittest
  
class MyTestCase(unittest.TestCase):
  
  # Returns true if GeeksforGeeks.txt file is not present and raises an EnvironmentError
  # Exception
  # In this example expected exception is RuntimeError while generated exception is
  # EnvironmentError, thus returns false
    def test_1(self):
        with self.assertRaises(RuntimeError):
            file = open("GeeksforGeeks.txt", 'r')
  
if __name__ == '__main__':
    unittest.main()

chevron_right


Output :

E
======================================================================
ERROR: test_1 (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/8520c06939bb0023b4f76f381b2c8cf2.py", line 11, in test_1
    file = open("GeeksforGeeks.txt", 'r')
FileNotFoundError: [Errno 2] No such file or directory: 'GeeksforGeeks.txt'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

When we try to open a file that does not exists, it raises an IOError which is sub class of EnvironmentError. In the above example, the unittest failed because the type of exception to be raised by function was expected to be of type RuntimeError, instead it raised an exception of EnvironmentError. Since the exception raised and exception expected are different, it produces an error.

Attention geek! Strengthen your foundations with the Python Programming Foundation Course and learn the basics.

To begin with, your interview preparations Enhance your Data Structures concepts with the Python DS Course.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.