如何编写只有在函数没有抛出预期异常时才会失败的单元测试呢?
当前回答
从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()
断言
在Python 3.5中,必须对上下文进行包装。否则你会得到一个TypeError
self.assertTrue('This is broken' in str(context.exception))
其他回答
从http://www.lengrand.fr/2011/12/pythonunittest-assertraises-raises-error/:
首先,这里是dum_function.py文件中对应的(仍然是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
完美!
... 对我来说也是完美的!!
非常感谢,Julien Lengrand-Lambert先生。
这个测试断言实际上返回一个假阳性。这是因为'assertRaises'中的lambda是引发类型错误的单元,而不是被测试的函数。
如何测试Python函数是否抛出异常? 如何编写只有在函数不抛出时才会失败的测试呢 意料之中的例外?
简短的回答:
利用自我。assertRaises方法作为上下文管理器:
def test_1_cannot_add_int_and_str(self):
with self.assertRaises(TypeError):
1 + '1'
示范
在Python shell中很容易演示最佳实践方法。
unittest库
在Python 2.7或3中:
import unittest
在Python 2.6中,你可以安装2.7的unittest库的backport,称为unittest2,并将其别名为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作为上下文管理器,以确保在记录错误的同时正确地捕获和清除错误。
我们也可以在没有上下文管理器的情况下编写它,参见测试二。第一个参数是您期望引发的错误类型,第二个参数是您正在测试的函数,其余的args和关键字args将被传递给该函数。
我认为仅仅使用上下文管理器要简单得多,可读性和可维护性更强。
运行测试
要运行测试:
unittest.main(exit=False)
在Python 2.6中,您可能需要以下内容:
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))
使用TestCase。从unittest模块中assertRaises(或testcase . failunlessraised),例如:
import mymod
class MyTestCase(unittest.TestCase):
def test1(self):
self.assertRaises(SomeCoolException, mymod.myfunc)
你的代码应该遵循这个模式(这是一个unittest模块风格测试):
def test_afunction_throws_exception(self):
try:
afunction()
except ExpectedException:
pass
except Exception:
self.fail('unexpected exception raised')
else:
self.fail('ExpectedException not raised')
在Python < 2.7中,此构造用于检查预期异常中的特定值。unittest函数assertRaises只检查是否引发了异常。
虽然所有的答案都很好,但我正在寻找一种方法来测试一个函数是否引发了异常,而不依赖于单元测试框架,也不必编写测试类。
最后我写下了以下内容:
def assert_error(e, x):
try:
e(x)
except:
return
raise AssertionError()
def failing_function(x):
raise ValueError()
def dummy_function(x):
return x
if __name__=="__main__":
assert_error(failing_function, 0)
assert_error(dummy_function, 0)
它在右边行上失败了:
Traceback (most recent call last):
File "assert_error.py", line 16, in <module>
assert_error(dummy_function, 0)
File "assert_error.py", line 6, in assert_error
raise AssertionError()
AssertionError
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 为什么Visual Studio 2015/2017/2019测试运行器没有发现我的xUnit v2测试
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if