您可以定义assertNotRaises通过重用对原执行的90%assertRaises的中unittest模块。使用这种方法,最终得到的assertNotRaises方法除了其反向失败条件外,其行为与相同assertRaises。
TLDR和现场演示
事实证明,向其中添加assertNotRaises方法非常容易unittest.TestCase(编写此答案所花的时间是代码的四倍,这使我花了大约四倍的时间)。这是该assertNotRaises方法的现场演示。就像一样assertRaises,您可以将callable和args传递给assertNotRaises,也可以在with语句中使用它。现场演示包括一个测试案例,演示了assertNotRaises预期的工作方式。
细节
assertRaisesin 的实现unittest相当复杂,但是通过一些巧妙的子类化,您可以覆盖和逆转其失败条件。
assertRaises是一个简短的方法,基本上只创建unittest.case._AssertRaisesContext类的实例并返回它(请参见unittest.case模块中的定义)。您可以_AssertNotRaisesContext通过继承_AssertRaisesContext并覆盖其__exit__方法来定义自己的类:
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可用的方法。