如何编写只有在函数没有抛出预期异常时才会失败的单元测试呢?
当前回答
由于我还没有看到任何关于如何检查我们是否在使用上下文管理器的接受列表中获得特定异常的详细解释,或其他异常细节,我将添加我的(在Python 3.8上检查)。
如果我只是想检查函数是否引发实例TypeError,我会写:
with self.assertRaises(TypeError):
function_raising_some_exception(parameters)
如果我想检查函数是否引发TypeError或IndexError,我会写:
with self.assertRaises((TypeError,IndexError)):
function_raising_some_exception(parameters)
如果我想要更多关于异常引发的细节,我可以在这样的上下文中捕获它:
# Here I catch any exception
with self.assertRaises(Exception) as e:
function_raising_some_exception(parameters)
# Here I check actual exception type (but I could
# check anything else about that specific exception,
# like it's actual message or values stored in the exception)
self.assertTrue(type(e.exception) in [TypeError,MatrixIsSingular])
其他回答
我刚刚发现Mock库提供了一个assertRaisesWithMessage()方法(在其unittest中)。TestCase子类),它不仅会检查是否引发了预期的异常,还会检查它是否与预期的消息一起引发:
from testcase import TestCase
import mymod
class MyTestCase(TestCase):
def test1(self):
self.assertRaisesWithMessage(SomeCoolException,
'expected message',
mymod.myfunc)
对于await/async aiounittest有一个稍微不同的模式:
https://aiounittest.readthedocs.io/en/latest/asynctestcase.html#aiounittest.AsyncTestCase
async def test_await_async_fail(self):
with self.assertRaises(Exception) as e:
await async_one()
如果你正在使用Python 3,为了断言异常及其消息,你可以在上下文管理器中使用assertRaises,并将消息作为msg关键字参数传递,如下所示:
import unittest
def your_function():
raise RuntimeError('your exception message')
class YourTestCase(unittest.TestCase):
def test(self):
with self.assertRaises(RuntimeError, msg='your exception message'):
your_function()
if __name__ == '__main__':
unittest.main()
我几乎在任何地方都使用doctest[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文档:23.2 doctest——测试交互式Python示例
如何测试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))
推荐文章
- 有没有办法在python中做HTTP PUT
- “foo Is None”和“foo == None”之间有什么区别吗?
- 类没有对象成员
- 在Visual Studio 2017中未发现单元测试
- Django模型“没有显式声明app_label”
- 熊猫能自动从CSV文件中读取日期吗?
- 在python中zip的逆函数是什么?
- 有效的方法应用多个过滤器的熊猫数据框架或系列
- 如何检索插入id后插入行在SQLite使用Python?
- 我如何在Django中添加一个CharField占位符?
- 如何在Python中获取当前执行文件的路径?
- 我如何得到“id”后插入到MySQL数据库与Python?
- super()失败,错误:TypeError "参数1必须是类型,而不是classobj"当父不继承对象
- Python内存泄漏
- 实现嵌套字典的最佳方法是什么?