Python unittest - 与 assertRaises 相对?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4319825/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 15:14:24  来源:igfitidea点击:

Python unittest - opposite of assertRaises?

pythonunit-testing

提问by glaucon

I want to write a test to establish that an Exception is not raised in a given circumstance.

我想编写一个测试来确定在给定情况下不会引发异常。

It's straightforward to test if an Exception israised ...

测试是否引发异常很简单......

sInvalidPath=AlwaysSuppliesAnInvalidPath()
self.assertRaises(PathIsNotAValidOne, MyObject, sInvalidPath) 

... but how can you do the opposite.

...但你怎么能反其道而行之

Something like this i what I'm after ...

这样的事情我就是我所追求的......

sValidPath=AlwaysSuppliesAValidPath()
self.assertNotRaises(PathIsNotAValidOne, MyObject, sValidPath) 

采纳答案by DGH

def run_test(self):
    try:
        myFunc()
    except ExceptionType:
        self.fail("myFunc() raised ExceptionType unexpectedly!")

回答by user9876

Just call the function. If it raises an exception, the unit test framework will flag this as an error. You might like to add a comment, e.g.:

只需调用该函数。如果它引发异常,单元测试框架会将其标记为错误。您可能想添加评论,例如:

sValidPath=AlwaysSuppliesAValidPath()
# Check PathIsNotAValidOne not thrown
MyObject(sValidPath)

回答by S.Lott

Hi - I want to write a test to establish that an Exception is not raised in a given circumstance.

嗨 - 我想编写一个测试来确定在给定情况下不会引发异常。

That's the default assumption -- exceptions are not raised.

这是默认假设——不会引发异常。

If you say nothing else, that's assumed in every single test.

如果你什么都不说,那在每一个测试中都是假设的。

You don't have to actually write an any assertion for that.

您实际上不必为此编写任何断言。

回答by glaucon

I am the original poster and I accepted the above answer by DGH without having first used it in the code.

我是原始海报,我接受了 DGH 的上述答案,而没有首先在代码中使用它。

Once I did use I realised that it needed a little tweaking to actually do what I needed it to do (to be fair to DGH he/she did say "or something similar" !).

一旦我确实使用过,我意识到它需要稍微调整才能真正做我需要它做的事情(公平地说,他/她确实说过“或类似的东西”!)。

I thought it was worth posting the tweak here for the benefit of others:

我认为值得在此处发布调整以造福他人:

    try:
        a = Application("abcdef", "")
    except pySourceAidExceptions.PathIsNotAValidOne:
        pass
    except:
        self.assertTrue(False)

What I was attempting to do here was to ensure that if an attempt was made to instantiate an Application object with a second argument of spaces the pySourceAidExceptions.PathIsNotAValidOne would be raised.

我在这里尝试做的是确保如果尝试使用第二个空格参数实例化 Application 对象,则会引发 pySourceAidExceptions.PathIsNotAValidOne 。

I believe that using the above code (based heavily on DGH's answer) will do that.

我相信使用上面的代码(主要基于 DGH 的答案)会做到这一点。

回答by hiwaylon

If you pass an Exception class to assertRaises(), a context manager is provided. This can improve the readability of your tests:

如果您将 Exception 类传递给assertRaises(),则会提供上下文管理器。这可以提高测试的可读性:

# raise exception if Application created with bad data
with self.assertRaises(pySourceAidExceptions.PathIsNotAValidOne):
    application = Application("abcdef", "")

This allows you to test error cases in your code.

这允许您测试代码中的错误情况。

In this case, you are testing the PathIsNotAValidOneis raised when you pass invalid parameters to the Application constructor.

在这种情况下,您正在测试PathIsNotAValidOne将无效参数传递给 Application 构造函数时引发的is 。

回答by AndyJost

I've found it useful to monkey-patch unittestas follows:

我发现猴子补丁很有用,unittest如下所示:

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

This clarifies intent when testing for the absence of an exception:

这在测试是否存在异常时阐明了意图:

self.assertMayRaise(None, does_not_raise)

This also simplifies testing in a loop, which I often find myself doing:

这也简化了循环中的测试,我经常发现自己在这样做:

# 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))

回答by tel

You can define assertNotRaisesby reusing about 90% of the original implementation of assertRaisesin the unittestmodule. With this approach, you end up with an assertNotRaisesmethod that, aside from its reversed failure condition, behaves identically to assertRaises.

您可以定义assertNotRaises通过重用对原执行的90%assertRaises的中unittest模块。使用这种方法,您最终会得到一种assertNotRaises方法,除了其反向失败条件外,其行为与 相同assertRaises

TLDR and live demo

TLDR 和现场演示

It turns out to be surprisingly easy to add an assertNotRaisesmethod to unittest.TestCase(it took me about 4 times as long to write this answer as it did the code). Here's a live demo of the assertNotRaisesmethod in action. Just like assertRaises, you can either pass a callable and args to assertNotRaises, or you can use it in a withstatement. The live demo includes a test cases that demonstrates that assertNotRaisesworks as intended.

事实证明,向其中添加assertNotRaises方法出奇地容易unittest.TestCase(我编写此答案的时间大约是编写代码的时间的 4 倍)。这是该assertNotRaises方法的现场演示。就像一样assertRaises,您可以将可调用对象和参数传递给assertNotRaises,也可以在with语句中使用它。现场演示包括一个测试用例,演示它assertNotRaises按预期工作。

Details

细节

The implementation of assertRaisesin unittestis fairly complicated, but with a little bit of clever subclassing you can override and reverse its failure condition.

assertRaisesin的实现unittest相当复杂,但是通过一些巧妙的子类化,您可以覆盖和逆转其失败条件。

assertRaisesis a short method that basically just creates an instance of the unittest.case._AssertRaisesContextclass and returns it (see its definition in the unittest.casemodule). You can define your own _AssertNotRaisesContextclass by subclassing _AssertRaisesContextand overriding its __exit__method:

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

Normally you define test case classes by having them inherit from TestCase. If you instead inherit from a subclass MyTestCase:

通常,您通过让它们继承自 来定义测试用例类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

all of your test cases will now have the assertNotRaisesmethod available to them.

您的所有测试用例现在都可以使用该assertNotRaises方法。

回答by lalit

you can try like that. try: self.assertRaises(None,function,arg1, arg2) except: pass if you don't put code inside try block it will through exception' AssertionError: None not raised " and test case will be failed. Test case will be pass if put inside try block which is expected behaviour.

你可以这样试试。try: self.assertRaises(None,function,arg1, arg2) 除外:通过,如果你不把代码放在 try 块中,它会通过异常' AssertionError: None not raise "并且测试用例将失败。测试用例将通过如果放在 try 块中,这是预期的行为。

回答by znotdead

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)) 

could be modified if you need to accept parameters.

如果需要接受参数可以修改。

call like

呼叫喜欢

self._assertNotRaises(IndexError, array, 'sort')

回答by anroyus

One straight forward way to ensure the object is initialized without any error is to test the object's type instance.

确保对象初始化没有任何错误的一种直接方法是测试对象的类型实例。

Here is an example :

这是一个例子:

p = SomeClass(param1=_param1_value)
self.assertTrue(isinstance(p, SomeClass))