Python unittest - opposite of assertRaises?
我想编写一个测试来确定在给定的情况下不会引发异常。
测试是否引发异常很简单…
1 2 | sInvalidPath=AlwaysSuppliesAnInvalidPath() self.assertRaises(PathIsNotAValidOne, MyObject, sInvalidPath) |
…但是你怎么能做相反的事情呢?
像这样的东西,我想要的……
1 2 | sValidPath=AlwaysSuppliesAValidPath() self.assertNotRaises(PathIsNotAValidOne, MyObject, sValidPath) |
1 2 3 4 5 | def run_test(self): try: myFunc() except ExceptionType: self.fail("myFunc() raised ExceptionType unexpectedly!") |
Hi - I want to write a test to establish that an Exception is not raised in a given circumstance.
这是默认假设——不会引发异常。
如果你什么都不说,那在每一个测试中都是假设的。
你不必为此写任何声明。
只需调用函数。如果它引发异常,单元测试框架会将其标记为错误。您可能需要添加评论,例如:
1 2 3 | sValidPath=AlwaysSuppliesAValidPath() # Check PathIsNotAValidOne not thrown MyObject(sValidPath) |
我是原来的海报,我接受了上面的回答,没有在代码中使用它。
一旦我使用了它,我意识到它需要一点小调整才能真正做到我需要它做的事情(公平地说,他/她确实说了"或类似的事情"!).
我认为为了其他人的利益,在这里张贴调整是值得的:
1 2 3 4 5 6 | try: a = Application("abcdef","") except pySourceAidExceptions.PathIsNotAValidOne: pass except: self.assertTrue(False) |
我在这里要做的是确保,如果试图用第二个空格参数实例化应用程序对象,那么PysourceAidexceptions.PathInotavalidone将被引发。
我相信使用上述代码(主要基于DGH的答案)可以做到这一点。
您可以通过在
事实证明,将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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 |
通常,您通过让测试用例类从
1 2 3 4 5 6 7 | 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 |
现在,您的所有测试用例都可以使用
我发现它对猴子补丁
1 2 3 4 5 6 7 8 9 10 11 | def assertMayRaise(self, exception, expr): if exception is None: try: expr() except: info = sys.exc_info() self.fail('%s raised' % repr(info[0])) else: self.assertRaises(exception, expr) unittest.TestCase.assertMayRaise = assertMayRaise |
这说明了在测试无异常情况时的意图:
1 | self.assertMayRaise(None, does_not_raise) |
这也简化了循环中的测试,我经常发现自己在做:
1 2 3 | # ValueError is raised only for op(x,x), op(y,y) and op(z,z). for i,(a,b) in enumerate(itertools.product([x,y,z], [x,y,z])): self.assertMayRaise(None if i%4 else ValueError, lambda: op(a, b)) |
如果将异常类传递给
1 2 3 | # raise exception if Application created with bad data with self.assertRaises(pySourceAidExceptions.PathIsNotAValidOne): application = Application("abcdef","") |
这允许您在代码中测试错误情况。
在这种情况下,您正在测试当您将无效参数传递给应用程序构造函数时引发的
1 2 3 4 5 6 7 8 | def _assertNotRaises(self, exception, obj, attr): try: result = getattr(obj, attr) if hasattr(result, '__call__'): result() except Exception as e: if isinstance(e, exception): raise AssertionError('{}.{} raises {}.'.format(obj, attr, exception)) |
如果需要接受参数,可以修改。
像呼叫
1 | self._assertNotRaises(IndexError, array, 'sort') |
你可以这样试试。尝试:self.assertraises(无,函数,arg1,arg2)除:通过如果不将代码放入try块中,它将通过异常"断言错误:无未引发",测试用例将失败。如果将测试用例放入预期行为的try块中,则该测试用例将通过。