Pergunta

I clearly have some fundamental misunderstanding on how to raise exceptions in python. I'm including the simplest example of what I'm trying (and failing) to do. I am trying to create a new exception, and properly test whether it working.

import random
import unittest

# Create new class of exception
class LearningError(Exception):
    pass

# Create function
def addition_no_four(first, second):
    """Add two numbers (as long as it isn't 4)."""
    if (first == 4) or (second == 4):
        raise LearningError("We don't take 4s!")
    return first + second

# Properly working example code that tests raising errors
class TestSequenceFunctions(unittest.TestCase):
    def setUp(self):
        self.seq = range(10)
    def test_shuffle(self):
        random.shuffle(self.seq)
        self.seq.sort()
        self.assertEqual(self.seq, range(10))
        self.assertRaises(TypeError, random.shuffle, (1,2,3))

# My code which tests 
class TestAddition(unittest.TestCase):
    def test_addition(self):
        """Test whether it works for 2 numbers (not 4)."""
        first = 2
        second = 5
        self.assertEqual(addition_no_four(first, second), 7)
    def test_raise(self):
        """Learn how to create an exception and test its implementation."""
        self.assertRaises(LearningError, addition_no_four(2, 4))

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

Which fails with the following message:

Traceback (most recent call last):
  File "test.py", line 34, in test_raise
    self.assertRaises(LearningError, addition_no_four(2, 4))
  File "test.py", line 12, in addition_no_four
    raise LearningError("We don't take 4s!")
LearningError: We don't take 4s!

----------------------------------------------------------------------
Ran 3 tests in 0.000s

FAILED (errors=1)

That doesn't happen (i.e., the example code correctly tests the previous exception. What do I need to change to make this kind of thing happen?

Foi útil?

Solução

There's just a small change. When you use assertRaises, be sure not to call the function directly. Instead, its arguments need to be passed as arguments to assertRaises. That allows the assertRaises test method to set-up a try/except before the function is invoked.

def test_raise(self):
    """Learn how to create an exception and test its implementation."""
    self.assertRaises(LearningError, addition_no_four, 2, 4)

You can also bypass this issue by using assertRaises as a content manager:

def test_raise(self):
    """Learn how to create an exception and test its implementation."""
    with self.assertRaises(LearningError):
        addition_no_four(2, 4)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top