Open In App

Test if a function throws an exception in Python

Improve
Improve
Like Article
Like
Save
Share
Report

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




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()


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




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()


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




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()


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




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()


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.



Last Updated : 20 Aug, 2020
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads