4

The following question was triggered by the discussion in this post.

Assume two files (foobar.py and foobar_unittest.py). File foobar.py contains a class (FooBar) with two functions (foo and bar). Function bar raises a built-in exception, function foo a user-defined exception.

# foobar.py
class MyException(Exception):
    pass
class FooBar:
    def __init__(self):
        pass
    def bar(self):
        raise ValueError('Hello World.')
    def foo(self):
        raise MyException('Hello World.')

.

# foobar_unittest.py
import unittest
import foobar as fb
class MyException(Exception):
    pass
class FooBarTestCases(unittest.TestCase):
    def test_bar(self):
        with self.assertRaises(ValueError):
            fb.FooBar().bar()
    def test_foo(self):
        with self.assertRaises(MyException):
            fb.FooBar().foo()
if __name__ == '__main__':
    unittest.main()

When running unit-test on foobar.py, why does the function raising the user-defined exception (foo) fail to pass the test?

>>> python2.7 foobar_unittest.py 
.E
======================================================================
ERROR: test_foo (__main__.FooBarTestCases)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "foobar_unittest.py", line 11, in test_foo
    fb.FooBar().foo()
  File "/a_path/foobar.py", line 9, in foo
    raise MyException('Hello World.')
MyException: Hello World.

----------------------------------------------------------------------
Ran 2 tests in 0.000s

FAILED (errors=1)
Community
  • 1
  • 1
Michael Gruenstaeudl
  • 1,609
  • 1
  • 17
  • 31
  • 1
    You defined two different `MyException` classes. You're not raising the same exception as the one you're trying to catch. – Vincent Savard Feb 18 '16 at 19:41
  • @VincentSavard If I were to remove the two lines in _foobar_unittest.py_ that define `MyException`, then I would receive the following error: `NameError: global name 'MyException' is not defined`. – Michael Gruenstaeudl Feb 18 '16 at 19:45

2 Answers2

2

import MyException from foobar, don't redefine it.

import unittest
from foobar import MyException
import foobar as fb

class FooBarTestCases(unittest.TestCase):
    def test_bar(self):
        with self.assertRaises(ValueError):
            fb.FooBar().bar()
    def test_foo(self):
        with self.assertRaises(MyException):
            fb.FooBar().foo()
if __name__ == '__main__':
    unittest.main()

This code should work now as

..
----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK
AlokThakur
  • 3,599
  • 1
  • 19
  • 32
0

Be aware that the same happens (happened to me) if you use reload to import your exceptions.

In my unittests I have the relevant imports like

from importlib import reload
import foobar
reload(foobar)
from foobar import MyException

This does not work, too, for whatever reason. Writing this just as

from foobar import MyException

will work. Then, of course, you have to reload the modules yourself.

In case you wonder why I am using reload: How do I unload (reload) a Python module?.

Dennis Proksch
  • 240
  • 2
  • 9