Python assertRaises для пользовательских исключений

Следующий вопрос был вызван обсуждением в этом сообщении.

Предположим, два файла (foobar.py и foobar_unittest.py). Файл foobar.py содержит класс (FooBar) с двумя функциями (foo и bar). Функция bar вызывает встроенное исключение, функция foo — пользовательское исключение.

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

Почему при выполнении модульного теста на foobar.py функция, вызывающая пользовательское исключение (foo), не проходит тест?

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

person Michael G    schedule 18.02.2016    source источник
comment
Вы определили два разных класса MyException. Вы не вызываете то же исключение, что и то, которое пытаетесь поймать.   -  person Vincent Savard    schedule 18.02.2016
comment
@VincentSavard Если бы я удалил две строки в foobar_unittest.py, определяющие MyException, я бы получил следующую ошибку: NameError: global name 'MyException' is not defined.   -  person Michael G    schedule 18.02.2016


Ответы (1)


импортируйте MyException из foobar, не переопределяйте его.

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

Этот код должен работать сейчас как

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

OK
person AlokThakur    schedule 18.02.2016
comment
Да, это был ответ на вопрос выше. Благодарю вас! - person Michael G; 18.02.2016