如何编写只有在函数没有抛出预期异常时才会失败的单元测试呢?


当前回答

我几乎在任何地方都使用doctest[1],因为我喜欢同时记录和测试我的函数。

看看这段代码:

def throw_up(something, gowrong=False):
    """
    >>> throw_up('Fish n Chips')
    Traceback (most recent call last):
    ...
    Exception: Fish n Chips

    >>> throw_up('Fish n Chips', gowrong=True)
    'I feel fine!'
    """
    if gowrong:
        return "I feel fine!"
    raise Exception(something)

if __name__ == '__main__':
    import doctest
    doctest.testmod()

如果您把这个例子放在一个模块中,并从命令行运行它,两个测试用例都会被评估和检查。

[1] Python文档:23.2 doctest——测试交互式Python示例

其他回答

我几乎在任何地方都使用doctest[1],因为我喜欢同时记录和测试我的函数。

看看这段代码:

def throw_up(something, gowrong=False):
    """
    >>> throw_up('Fish n Chips')
    Traceback (most recent call last):
    ...
    Exception: Fish n Chips

    >>> throw_up('Fish n Chips', gowrong=True)
    'I feel fine!'
    """
    if gowrong:
        return "I feel fine!"
    raise Exception(something)

if __name__ == '__main__':
    import doctest
    doctest.testmod()

如果您把这个例子放在一个模块中,并从命令行运行它,两个测试用例都会被评估和检查。

[1] Python文档:23.2 doctest——测试交互式Python示例

我之前回答中的代码可以简化为:

def test_afunction_throws_exception(self):
    self.assertRaises(ExpectedException, afunction)

如果一个函数有参数,就像这样把它们传递给assertRaises:

def test_afunction_throws_exception(self):
    self.assertRaises(ExpectedException, afunction, arg1, arg2)

如果在这个类中将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只检查是否引发了异常。

我刚刚发现Mock库提供了一个assertRaisesWithMessage()方法(在其unittest中)。TestCase子类),它不仅会检查是否引发了预期的异常,还会检查它是否与预期的消息一起引发:

from testcase import TestCase

import mymod

class MyTestCase(TestCase):
    def test1(self):
        self.assertRaisesWithMessage(SomeCoolException,
                                     'expected message',
                                     mymod.myfunc)