如何编写一个unittest,只有在函数没有抛出预期的异常时才会失败?你如何测试Python函数抛出异常?
回答
使用TestCase.assertRaises
(或TestCase.failUnlessRaises
)从单元测试模块,例如:
import mymod
class MyTestCase(unittest.TestCase):
def test1(self):
self.assertRaises(SomeCoolException, mymod.myfunc)
看看unittest
模块的assertRaises方法。
您的代码应遵循此模式(这是一个单元测试模块的风格测试):
def test_afunction_throws_exception(self):
try:
afunction()
except ExpectedException:
pass
except Exception as e:
self.fail('Unexpected exception raised:', e)
else:
self.fail('ExpectedException not raised')
关于Python < 2.7此构造对于检查预期异常中的特定值很有用。单元测试功能assertRaises
仅检查是否引发异常。
在我以前的答案的代码可以简化为:
def test_afunction_throws_exception(self):
self.assertRaises(ExpectedException, afunction)
如果机能缺失接受参数,只需将它们传递到assertRaises这样的:
def test_afunction_throws_exception(self):
self.assertRaises(ExpectedException, afunction, arg1, arg2)
如何处理控制台中存在的异常的追踪?也就是说,在其他方面通过的测试中有一个追溯。 – MadPhysicist 2017-03-15 14:13:13
@MadPhysicist我看不到你在说什么。我刚刚在Python 2.6和3.5上进行了测试 - 没有将Tracebacks打印到控制台。也许你正在打印或记录代码中的回溯? – 2017-04-04 17:43:55
我用文档测试 [1 ]几乎无处不在,因为我喜欢我同时记录和测试我的功能的事实。
看一看这段代码:
def throw_up(something, gowrong=False):
"""
>>> throw_up('Fish n Chips')
Traceback (most recent call last):
...
Exception: Fish n Chips
>>> throw_up('Fish n Chips', gowrong=True)
'I feel fine!'
"""
if gowrong:
return "I feel fine!"
raise Exception(something)
if __name__ == '__main__':
import doctest
doctest.testmod()
如果你把这个例子中的模块中,并通过命令行测试案例进行评估,并检查运行它。
[1] Python documentation: 23.2 doctest -- Test interactive Python examples
我刚刚发现Mock library提供assertRaisesWithMessage()方法(在它的子类unittest.TestCase生成),这将不仅检查了预期的异常升高,而且它是与预期的消息提出:
from testcase import TestCase
import mymod
class MyTestCase(TestCase):
def test1(self):
self.assertRaisesWithMessage(SomeCoolException,
'expected message',
mymod.myfunc)
因为Python 2.7,你可以使用上下文管理器来获得抛出的实际Exception对象的保持:
import unittest
def broken_function():
raise Exception('This is broken')
class MyTestCase(unittest.TestCase):
def test(self):
with self.assertRaises(Exception) as context:
broken_function()
self.assertTrue('This is broken' in context.exception)
if __name__ == '__main__':
unittest.main()
http://docs.python.org/dev/library/unittest.html#unittest.TestCase.assertRaises
在的Python 3.5,你必须包装在str
context.exception
,否则你会得到一个TypeError
self.assertTrue('This is broken' in str(context.exception))
您可以使用assertRaises从单元测试模块
import unittest
class TestClass():
def raises_exception(self):
raise Exception("test")
class MyTestCase(unittest.TestCase):
def test_if_method_raises_correct_exception(self):
test_class = TestClass()
# note that you dont use() when passing the method to assertRaises
self.assertRaises(Exception, test_class.raises_exception)
来自:http://www.lengrand.fr/2011/12/pythonunittest-assertraises-raises-error/
首先,这里是文件dum_function中相应的(仍然是dum:p)函数。潘岳:
def square_value(a):
"""
Returns the square value of a.
"""
try:
out = a*a
except TypeError:
raise TypeError("Input should be a string:")
return out
这里是要进行的测试(仅适用于本次测试插入):
import dum_function as df # import function module
import unittest
class Test(unittest.TestCase):
"""
The class inherits from unittest
"""
def setUp(self):
"""
This method is called before each test
"""
self.false_int = "A"
def tearDown(self):
"""
This method is called after each test
"""
pass
#---
## TESTS
def test_square_value(self):
# assertRaises(excClass, callableObj) prototype
self.assertRaises(TypeError, df.square_value(self.false_int))
if __name__ == "__main__":
unittest.main()
现在我们可以测试我们的功能!以下是试图运行测试时发生的情况:
======================================================================
ERROR: test_square_value (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_dum_function.py", line 22, in test_square_value
self.assertRaises(TypeError, df.square_value(self.false_int))
File "/home/jlengrand/Desktop/function.py", line 8, in square_value
raise TypeError("Input should be a string:")
TypeError: Input should be a string:
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (errors=1)
TypeError被触发,并生成测试失败。问题是这正是我们想要的行为:s。
为了避免这种错误,只需在测试呼叫使用lambda运行函数:
self.assertRaises(TypeError, lambda: df.square_value(self.false_int))
最终输出:
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
完美!
...对我来说也是完美的!
Thansk很多朱利安·朗格朗兰伯特先生
你可以建立自己的contextmanager
检查是否异常升高。
import contextlib
@contextlib.contextmanager
def raises(exception):
try:
yield
except exception as e:
assert True
else:
assert False
然后你就可以使用raises
这样的:
with raises(Exception):
print "Hola" # Calls assert False
with raises(Exception):
raise Exception # Calls assert True
如果使用的是pytest
,这件事情已经落实。你可以做pytest.raises(Exception)
:
例子:
def test_div_zero():
with pytest.raises(ZeroDivisionError):
1/0
而结果:
[email protected]$ py.test
================= test session starts =================
platform linux2 -- Python 2.6.6 -- py-1.4.20 -- pytest-2.5.2 -- /usr/bin/python
collected 1 items
tests/test_div_zero.py:6: test_div_zero PASSED
你如何测试一个Python函数抛出一个异常?
如何编写一个测试,只有在函数不会将 预期的异常抛出时才会失败?
答案很简单:
使用self.assertRaises
方法作为上下文管理器:
def test_1_cannot_add_int_and_str(self):
with self.assertRaises(TypeError):
1 + '1'
示范
的最佳实践方法是很容易在Python外壳来证明。
的unittest
库
在Python 2。7或3:
import unittest
在Python 2.6,你可以安装2.7的unittest
库的反向移植,叫,只是别名为unittest
:
import unittest2 as unittest
示例测试
现在,将Python的类型安全性粘贴到您的Python shell中:
class MyTestCase(unittest.TestCase):
def test_1_cannot_add_int_and_str(self):
with self.assertRaises(TypeError):
1 + '1'
def test_2_cannot_add_int_and_str(self):
import operator
self.assertRaises(TypeError, operator.add, 1, '1')
测试人员使用assertRaises
作为上下文管理器,可确保在记录时正确捕获并清除错误。
我们也可以写它没有上下文管理器,见测试二。第一个参数是您期望提出的错误类型,第二个参数,您正在测试的函数,剩余的参数和关键字参数将被传递给该函数。
我认为它更简单,更易读,更易于使用上下文管理器。
运行测试
运行测试:
unittest.main(exit=False)
在Python 2.6,你可能会need the following:
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))
而且终端应该输出如下:
..
----------------------------------------------------------------------
Ran 2 tests in 0.007s
OK
<unittest2.runner.TextTestResult run=2 errors=0 failures=0>
我们可以看到,正如我们预期的那样,试图在TypeError
中添加1
和'1'
。
更详细的输出,试试这个:
unittest.TextTestRunner(verbosity=2).run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))
- 1. 你如何测试函数抛出异常?
- 2. Python的 - 测试属性抛出异常
- 3. 如何测试函数是否不抛出异常?
- 4. 如何测试异常抛出midje
- 5. 如何测试抛出异常
- 6. 如何测试没有异常抛出?
- 7. Spock抛出异常测试
- 8. Python:你如何测试嵌套函数?
- 9. 测试失败,因为抛出异常
- 10. 的Arquillian测试抛出NoSuchElementException异常
- 11. mvn测试抛出空指针异常
- 12. 测试控制器抛出的异常
- 13. Mockito测试void方法抛出异常
- 14. 测试应该失败抛出异常
- 15. Jasmine通过测试,抛出异常
- 16. .NET ComboBox.Items.Add(“测试值”)抛出异常
- 17. 如何检测CLR抛出的异常?
- 18. C#:你提出或抛出异常?
- 19. 错误测试抛出的异常测试
- 20. 如何使用Python unittest assertRaises来测试该函数不会抛出任何异常?
- 21. 如何测试异常与Junit一起抛出
- 22. 我如何测试每条线都抛出相同的异常?
- 23. 如何测试特定异常是否不被抛出?
- 24. 如何在Android中测试断言抛出异常
- 25. 如何测试Clojure中抛出的异常?
- 26. 如何在单元测试中模拟抛出异常?
- 27. 如何在本单元测试中抛出“N”异常?
- 28. Python单元测试:我如何测试异常中的参数?
- 29. 魔术异常抛出抛出异常
- 30. 抛出异常抛出异常
是有办法做到这相反?就像它只有在函数抛出异常时才会失败? – BUInvent 2017-07-26 19:44:59
@BUInvent,是的,有:https://stackoverflow.com/a/4319870/3405140 – moertel 2017-07-27 16:23:47
请注意,要将参数传递给`myfunc`,您需要将它们作为参数添加到assertRaises调用中。见Daryl Spitzer的回答。 – cbron 2018-02-21 16:43:15