无法通过 Python 中的 assertRaises 测试
Unable to pass assertRaises test in Python
所以,我有世界上最微不足道的例子。这是我要测试的class:
# 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)
它真的很有趣,因为它是有争议的。一方面,测试表明 "Exception not raised by doit",但它下面的一行清楚地打印出来自异常块的消息。那么,我在这里做错了什么???谢谢!
assertRaises
失败,因为实际上没有引发异常。好吧,它被提出但在 doit()
方法中用 except
处理。问题在这里:
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
assertRaises
是关于函数可见行为的断言,而不是其内部。它断言所述异常通过函数的 out。 assertRaises
不关心函数内部处理的任何异常。
直接回答你的问题,你收到这条消息的原因是因为这个断言:
self.assertRaises(Exception, self.my_class.doit, name, params)
您正在测试以确保引发异常。但是您的 try/except 抑制了这一点。如果你真的删除你的 try/except 你的测试实际上会通过,因为现在你的方法会引发。
既然你不想这样做,你应该做的是在引发异常时测试你的方法的行为。最后,您要确保 print
方法在您的 except 中被调用。我在下面整理了一个示例来帮助理解这一点。
记住 @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
方法 的行为方式 异常被提出。
在这一点上,我建议查看 unittest and mock 背后的文档,以更熟悉您可以用测试做什么,但这里有一个使用模拟补丁来测试您的行为的示例如果引发异常,代码:
@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()
所以,我有世界上最微不足道的例子。这是我要测试的class:
# 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)
它真的很有趣,因为它是有争议的。一方面,测试表明 "Exception not raised by doit",但它下面的一行清楚地打印出来自异常块的消息。那么,我在这里做错了什么???谢谢!
assertRaises
失败,因为实际上没有引发异常。好吧,它被提出但在 doit()
方法中用 except
处理。问题在这里:
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
assertRaises
是关于函数可见行为的断言,而不是其内部。它断言所述异常通过函数的 out。 assertRaises
不关心函数内部处理的任何异常。
直接回答你的问题,你收到这条消息的原因是因为这个断言:
self.assertRaises(Exception, self.my_class.doit, name, params)
您正在测试以确保引发异常。但是您的 try/except 抑制了这一点。如果你真的删除你的 try/except 你的测试实际上会通过,因为现在你的方法会引发。
既然你不想这样做,你应该做的是在引发异常时测试你的方法的行为。最后,您要确保 print
方法在您的 except 中被调用。我在下面整理了一个示例来帮助理解这一点。
记住 @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
方法 的行为方式 异常被提出。
在这一点上,我建议查看 unittest and mock 背后的文档,以更熟悉您可以用测试做什么,但这里有一个使用模拟补丁来测试您的行为的示例如果引发异常,代码:
@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()