你可以通过重用unittest模块中90%的assertRaises原始实现来定义assertNotRaises。使用这种方法,您最终得到一个assertNotRaises方法,除了它的反向失败条件外,它的行为与assertRaises完全相同。
TLDR和现场演示
在unittest中添加assertNotRaises方法非常简单。TestCase(写这个答案的时间是写代码的4倍)。下面是assertNotRaises方法的现场演示。就像assertRaises一样,你可以传递一个可调用对象和参数给assertNotRaises,或者你可以在with语句中使用它。现场演示包括一个测试用例,演示assertNotRaises按预期工作。
细节
在unittest中实现assertRaises是相当复杂的,但是通过一些聪明的子类化,你可以覆盖和逆转它的失败条件。
assertRaises是一个简短的方法,基本上只创建unittest.case的一个实例。_AssertRaisesContext类并返回它(参见unittest. context中的定义)。模块)。你可以通过继承_AssertRaisesContext的子类并覆盖它的__exit__方法来定义你自己的_AssertNotRaisesContext类:
import traceback
from unittest.case import _AssertRaisesContext
class _AssertNotRaisesContext(_AssertRaisesContext):
def __exit__(self, exc_type, exc_value, tb):
if exc_type is not None:
self.exception = exc_value.with_traceback(None)
try:
exc_name = self.expected.__name__
except AttributeError:
exc_name = str(self.expected)
if self.obj_name:
self._raiseFailure("{} raised by {}".format(exc_name,
self.obj_name))
else:
self._raiseFailure("{} raised".format(exc_name))
else:
traceback.clear_frames(tb)
return True
通常,您通过让它们继承TestCase来定义测试用例类。如果你从一个子类MyTestCase继承:
class MyTestCase(unittest.TestCase):
def assertNotRaises(self, expected_exception, *args, **kwargs):
context = _AssertNotRaisesContext(expected_exception, self)
try:
return context.handle('assertNotRaises', args, kwargs)
finally:
context = None
现在所有的测试用例都有assertNotRaises方法可用。