Levi Campbell
Levi Campbell

Reputation: 6095

Pass a Python unittest if an exception isn't raised

In the Python unittest framework, is there a way to pass a unit test if an exception wasn't raised, and fail with an AssertRaise otherwise?

Upvotes: 30

Views: 39944

Answers (4)

Enrico Sodenkamp
Enrico Sodenkamp

Reputation: 1

I stumbled upon this question while looking for an answer to this obvious problem. Whilst the suggested solutions with try/except are fine, I found that I ended up with uncovered lines of code in coverage and that doesn't sit well with me. So I have come up with another solution, whilst not perfect, works for functions that only throw exceptions.

def check_raises(obj):
    if obj.condition is True:
        raise Exception('Condition is true')

In order to successfully test this function, I have resorted to using assertIsNone. The below code covers both cases.

import unittest


class Object:
    def __init__(self):
        self.condition = None


class TestCheckRaises(unittest.TestCase):
    def test_check_raises_exception(self):
        obj = Object()
        obj.condition = True
        self.assertRaises(Exception, check_raises, obj)

    def test_check_raises_no_exception(self):
        obj = Object()
        obj.condition = False
        self.assertIsNone(check_raises(obj))

I am with the original poster that a assertNotRaises would be nice, but failing that, assertIsNone is perfectly acceptable for functions that do not return a value.

Upvotes: 0

Asclepius
Asclepius

Reputation: 63252

Simply call your functionality, e.g. do_something(). If an unhandled exception gets raised, the test automatically fails! There is really no reason to do anything else. This is also the reason why assertDoesNotRaise() does not exist.


Credit: comment by Sven

Upvotes: 5

Paul Bissex
Paul Bissex

Reputation: 1704

Many of the comments on this page treat errors and failures as equivalent, which they are not. The right solution in my opinion is to explicitly fail the test if the exception is raised. E.g.:

def test_does_not_error(self):
    try:
        code_under_test()
    except ThatException:
        self.fail("code_under_test raised ThatException")

Upvotes: 31

johnsyweb
johnsyweb

Reputation: 141770

If I understand your question correctly, you could do something like this:

def test_does_not_raise_on_valid_input(self):
    raised = False
    try:
        do_something(42)
    except:
        raised = True
    self.assertFalse(raised, 'Exception raised')

...assuming that you have a corresponding test that the correct Exception gets raised on invalid input, of course:

def test_does_raise_on_invalid_input(self):
    self.assertRaises(OutOfCheese, do_something, 43)

However, as pointed out in the comments, you need to consider what it is that you are actually testing. It's likely that a test like...

def test_what_is_42(self):
    self.assertEquals(do_something(42), 'Meaning of life')

...is better because it tests the desired behaviour of the system and will fail if an exception is raised.

Upvotes: 36

Related Questions