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


当前回答

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

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

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

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

其他回答

使用unittest进行单元测试将是首选,但如果您想快速修复,我们可以捕获异常,将其赋值给一个变量,并查看该变量是否是该异常类的实例。

假设我们的坏函数抛出一个ValueError。

    try:
      bad_function()
    except ValueError as e:
      assert isinstance(e, ValueError)

如果在这个类中将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

使用TestCase。从unittest模块中assertRaises(或testcase . failunlessraised),例如:

import mymod

class MyTestCase(unittest.TestCase):
    def test1(self):
        self.assertRaises(SomeCoolException, mymod.myfunc)

由于我还没有看到任何关于如何检查我们是否在使用上下文管理器的接受列表中获得特定异常的详细解释,或其他异常细节,我将添加我的(在Python 3.8上检查)。

如果我只是想检查函数是否引发实例TypeError,我会写:

with self.assertRaises(TypeError):
    function_raising_some_exception(parameters)

如果我想检查函数是否引发TypeError或IndexError,我会写:

with self.assertRaises((TypeError,IndexError)):
    function_raising_some_exception(parameters)

如果我想要更多关于异常引发的细节,我可以在这样的上下文中捕获它:

# Here I catch any exception
with self.assertRaises(Exception) as e:
    function_raising_some_exception(parameters)

# Here I check actual exception type (but I could
# check anything else about that specific exception,
# like it's actual message or values stored in the exception)
self.assertTrue(type(e.exception) in [TypeError,MatrixIsSingular])

我几乎在任何地方都使用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示例