Check error (assertRaises)

Check error (assertRaises)#

Sometimes programs are designed to throw exceptions in certain cases. So we need a way to test whether an exception has been thrown in that case. In this subsection I want to pay attention to such a case.

There is a special tool that allows you to check whether an exception was raised: unittest.TestCase.assertRaises.

Check more in the specific page of the official documentation.


As a typical example, let’s consider the function defined below.

import unittest

def my_division(a, b):
    if b == 0:
        raise ValueError("Division by zero is detected!")
    return a/b

It is the implementation of a division function that raises an error when the denominator is zero. Let’s test if it works:

my_division(5, 0)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[3], line 1
----> 1 my_division(5, 0)

Cell In[2], line 3, in my_division(a, b)
      1 def my_division(a,b):
      2     if b == 0:
----> 3         raise ValueError("Division by zero is detected!")
      4     return a/b

ValueError: Division by zero is detected!

Each time the b parameter is set to 0, a ValueError will be raised.

Syntax#

Typical syntax is:

assertRaises(<expected exception>, <function>, *<arguments that trigger the error>).

You don’t need to call the function directly; instead, you pass it along with the test case details to unittest.TestCase.assertRaises.


In the example below, the first test triggers a ValueError in my_division, while the second does not. This ensures that if an error does not occur when expected, you’ll be alerted:

class MyCase(unittest.TestCase):
    def test_sucessfull(self):
        '''
        Case where division by zero occurs.
        So testing for it will be successful.
        '''
        self.assertRaises(
            ValueError,
            my_division,
            10, 0
        )

    def test_error(self):
        '''
        Case where division by zero doesn't happen.
        So testing for it won't finish well.
        '''
        self.assertRaises(
            ValueError,
            my_division,
            10,2
        )

ans = unittest.main(argv=[''], verbosity=2, exit=False)
del MyCase
test_error (__main__.MyCase)
Case where division by zero doesn't happen. ... FAIL
test_sucessfull (__main__.MyCase)
Case where division by zero occurs. ... ok

======================================================================
FAIL: test_error (__main__.MyCase)
Case where division by zero doesn't happen.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/ipykernel_19354/169255605.py", line 20, in test_error
    self.assertRaises(
AssertionError: ValueError not raised by my_division

----------------------------------------------------------------------
Ran 2 tests in 0.005s

FAILED (failures=1)

As a result we have that one test goes fine, but the second leads to the error.

The second option is to use unittest.TestCase.assertRaises as a context manager and call the function under consideration within this context.


The following example demonstrates how it can be applied to the my_division function.

class MyCase(unittest.TestCase):
    def test_case(self):
        with self.assertRaises(ValueError):
            my_division(10, 0)

ans = unittest.main(argv=[''], verbosity=2, exit=False)
del MyCase
test_case (__main__.MyCase) ... ok

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

OK

Properties of exception#

If you need to check if the raised exception has specific properties, use the context manager syntax. The context object will have an exception attribute that contains the raised exception.


The following cell demonstrates the use of unittest.TestCase().assertRaises(ValueError) to check that a ValueError is raised within the specified context.

with unittest.TestCase().assertRaises(ValueError) as raise_value:
    raised_error = ValueError("Something wrong")
    raise raised_error

display(raise_value.exception)
display(raised_error is raise_value.exception)
ValueError('Something wrong')
True

As a result, the context object raise_value contains an attribute exception, which is the literal exception object raised within the context.