如何编写只有在函数没有抛出预期异常时才会失败的单元测试呢?
当前回答
从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))
其他回答
有4个选项(你会在最后找到完整的例子):
assertRaises与上下文管理器
def test_raises(self):
with self.assertRaises(RuntimeError):
raise RuntimeError()
如果你想检查异常消息(参见下面的"assertRaisesRegex with context manager"选项来检查它的一部分):
def test_raises(self):
with self.assertRaises(RuntimeError) as error:
raise RuntimeError("your exception message")
self.assertEqual(str(error.exception), "your exception message")
assertRaises一行程序
注意:这里使用的函数不是函数调用,而是可调用函数(不带圆括号)。
def test_raises(self):
self.assertRaises(RuntimeError, your_function)
assertRaisesRegex与上下文管理器
第二个参数是正则表达式,是必选项。当您只想检查部分异常消息时,非常方便。
def test_raises_regex(self):
with self.assertRaisesRegex(RuntimeError, r'.* exception message'):
raise RuntimeError('your exception message')
assertRaisesRegex一行程序
第二个参数是正则表达式,是必选项。当您只想检查部分异常消息时,非常方便。
注意:这里使用的函数不是函数调用,而是可调用函数(不带圆括号)。
def test_raises_regex(self):
self.assertRaisesRegex(RuntimeError, r'.* exception message', your_function)
完整的代码示例:
import unittest
def your_function():
raise RuntimeError('your exception message')
class YourTestCase(unittest.TestCase):
def test_1_raises_context_manager(self):
with self.assertRaises(RuntimeError):
your_function()
def test_1b_raises_context_manager_and_error_message(self):
with self.assertRaises(RuntimeError) as error:
your_function()
self.assertEqual(str(error.exception), "your exception message")
def test_2_raises_oneliner(self):
self.assertRaises(RuntimeError, your_function)
def test_3_raises_regex_context_manager(self):
with self.assertRaisesRegex(RuntimeError, r'.* exception message'):
your_function()
def test_4_raises_regex_oneliner(self):
self.assertRaisesRegex(RuntimeError, r'.* exception message', your_function)
if __name__ == '__main__':
unittest.main()
虽然这取决于开发人员遵循哪种风格,但我更喜欢使用上下文管理器的两种方法。
使用TestCase。从unittest模块中assertRaises(或testcase . failunlessraised),例如:
import mymod
class MyTestCase(unittest.TestCase):
def test1(self):
self.assertRaises(SomeCoolException, mymod.myfunc)
如果在这个类中将stock_id设置为Integer将抛出错误,则将引发TypeError,如果发生这种情况,则测试将通过,否则将失败
def set_string(prop, value):
if not isinstance(value, str):
raise TypeError("i told you i take strings only ")
return value
class BuyVolume(ndb.Model):
stock_id = ndb.StringProperty(validator=set_string)
from pytest import raises
buy_volume_instance: BuyVolume = BuyVolume()
with raises(TypeError):
buy_volume_instance.stock_id = 25
你的代码应该遵循这个模式(这是一个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只检查是否引发了异常。
使用unittest进行单元测试将是首选,但如果您想快速修复,我们可以捕获异常,将其赋值给一个变量,并查看该变量是否是该异常类的实例。
假设我们的坏函数抛出一个ValueError。
try:
bad_function()
except ValueError as e:
assert isinstance(e, ValueError)
推荐文章
- 如何直接从测试驱动程序调用自定义的Django manage.py命令?
- 我如何让红宝石打印一个完整的回溯而不是截断一个?
- Visual Studio:如何打破处理异常?
- 如何重置笑话模拟函数调用计数之前,每次测试
- 如何在Flask-SQLAlchemy中按id删除记录
- 在Python中插入列表的第一个位置
- Python Pandas只合并某些列
- 如何在一行中连接两个集而不使用“|”
- 从字符串中移除前缀
- 代码结束时发出警报
- 如何在Python中按字母顺序排序字符串中的字母
- 在matplotlib中将y轴标签添加到次要y轴
- 如何消除数独方块的凹凸缺陷?
- 为什么出现这个UnboundLocalError(闭包)?
- 使用Python请求的异步请求