无法在Python中传递assertRaises测试

时间:2015-11-18 17:29:07

标签: python python-unittest

所以,我在世界范例中有最微不足道的。这是我要测试的课程:

# My_Class.py
class My_Class(object):    
    @staticmethod     
    def doit(name, params):
        try:
            raise Exception("This is my error message")
        except Exception:
            print("Exception: I raised Exception")

这是测试人员本身:

# test.py
import unittest
from My_Class import My_Class

class Test_MyClass(unittest.TestCase):

    def setUp(self):
        self.my_class = My_Class()   

    def test_my_class(self):
        name = "Abrakadabra"
        params = {}
        self.assertRaises(Exception, self.my_class.doit, name, params)

这就是我在控制台中看到的,当我运行我的test.py:

$ nosetests test.py
F
======================================================================
FAIL: test_my_class (test.Test_MyClass)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ....
nose.proxy.AssertionError: Exception not raised by doit
-------------------- >> begin captured stdout << ---------------------
Exception: I raised Exception

--------------------- >> end captured stdout << ----------------------

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

FAILED (failures=1)

这是非常重要的,因为它是有争议的。一方面测试说“异常不是由doit引发的”,但是它下面的一行清楚地打印出来自Exception块的消息。那么,我在这里做错了什么?谢谢!

3 个答案:

答案 0 :(得分:3)

要直接回答您的问题,您收到该消息的原因是因为这个断言:

self.assertRaises(Exception, self.my_class.doit, name, params)

您正在测试以确保引发异常。但你的尝试/除了抑制这个。如果你真的删除你的尝试/除了你的测试实际上会通过,因为现在你的方法将提高。

由于您不想这样做,所以您应该做的是在引发异常时测试方法的行为。最终,您需要确保在您的except中调用print方法。我在下面举了一个例子来帮助理解这一点。

请记住@ user2357112提到的内容,在单元测试时要记住这一点非常重要,这里有一个示例来帮助扩展它以提供您尝试做的实际用途:

让我们把一些方法放在一起:

def some_method():
    pass

我们现在将其放入您定义的静态方法中:

# My_Class.py
class My_Class(object):    
    @staticmethod     
    def doit(name, params):
        try:
            some_method()
        except Exception:
            print("Exception: I raised Exception")

现在,当涉及到您的单元测试时,您希望测试方法doit行为。考虑到这一点,在这种情况下您要做的是测试some_method将引发异常,并且您将验证doit方法行为如何引发异常。

此时,我建议您查看unittestmock背后的文档,以便更熟悉您可以对测试做些什么,但这里有一个使用模拟修补来测试的示例如果引发异常,则代码的行为:

@patch('builtins.print')
@patch('__main__.some_method')
def test_my_class(self, m_some_method, m_print):
    name = "Abrakadabra"
    params = {}
    # have the side_effect raise the exception when some_method is called in doit
    m_some_method.side_effect = Exception()

    self.my_class.doit(name, params)

    # check to make sure you caught the exception by checking print was called
    self.assertEqual(m_print.call_count, 1)

当你把它们放在一起时,以下是我在我的最后运行的功能代码,你可以随意使用以了解发生了什么:

def some_method():
    pass

# My_Class.py
class My_Class(object):    
    @staticmethod     
    def doit(name, params):
        try:
            some_method()
        except Exception:
            print("Exception: I raised Exception")


# test.py
import unittest
from mock import patch

class Test_MyClass(unittest.TestCase):

    def setUp(self):
        self.my_class = My_Class()

@patch('builtins.print')
@patch('__main__.some_method')
def test_my_class(self, m_some_method, m_print):
    name = "Abrakadabra"
    params = {}
    m_some_method.side_effect = Exception()
    self.my_class.doit(name, params)
    self.assertEqual(m_print.call_count, 1)


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

答案 1 :(得分:1)

assertRaises失败,因为实际上没有引发任何异常。好吧,它被提出但在except方法中使用doit()处理。问题出在这里:

try:
    raise Exception("This is my error message")
except Exception:
    print("Exception: I raised Exception")

您正在提出异常,然后在不重新提升的情况下捕获它。从调用者(assertRaises是你的情况下的调用者)的角度来看,在函数调用期间没有抛出任何错误。 重新引发异常也允许调用者处理异常。在打印后放置raise

try:
    raise Exception("This is my error message")
except Exception:
    print("Exception: I raised Exception")
    raise  # re-raising

另见Handling Exceptions

答案 2 :(得分:1)

assertRaises是关于函数可见行为的断言,而不是它的内部。它断言所述异常通过该函数的 out 。在函数内部处理的任何异常都不是assertRaises关注的问题。