Python单元测试:将AssertionError设为错误而不是失败

时间:2019-03-25 11:31:09

标签: python python-unittest

Python 2.7。 The unittest doc说:

  

为简化现有测试套件的迁移,unittest支持引发AssertionError的测试以指示测试失败。但是,建议您改用显式的TestCase.fail *()和TestCase.assert *()方法,因为将来的unittest版本可能会区别对待AssertionError。

我在测试的代码中使用了很多assert语句,但是这些断言的失败实际上应该是一个测试错误(即“代码无法使用这些输入正确运行”)而不是失败(即“代码给出了错误的输出”)。

我可以看到以下可能的解决方案:

  1. 重写测试后的代码以引发类型更好的异常
  2. 将除测试断言本身(self.assertSomething(...))以外的所有内容包装在try...except AssertionError: raise SomeOtherException块中
  3. 更改单元测试的行为,以便它考虑这些错误而不是失败。

选项1需要花费一些时间,而选项2感觉很笨拙。选项3最适合我,但是可以使用吗? (以防万一:不,我不能切换到Python 3.)我在网上看不到任何东西,但是很难使用特定的关键字。

MWE:

import unittest


def add_one_to_int(a):
    assert isinstance(a, int)
    return a + 1


class TestAddOne(unittest.TestCase):
    def test_one_plus_one_is_three(self):
        # This tests fails with
        #   AssertionError: 2 != 3
        # which is fine
        self.assertEqual(add_one_to_int(1), 3)  

    def test_add_one_to_str(self):
        # This tests fails with
        #   AssertionError
        # when I would rather have it an error
        add_one_to_int('some string')

if __name__ == '__main__':
    unittest.main(verbosity=2)  # 2 failures instead of 1 failure, 1 error

1 个答案:

答案 0 :(得分:1)

我认为选项3可以通过类属性“ failureException”实现,正如Python 2.7的unittest文档中所定义的那样:

  

failureException :   此类属性给出了test方法引发的异常。如果测试框架需要使用特殊的异常(可能带有其他信息),则它必须将该异常子类化,以便与框架“公平竞争”。此属性的初始值为AssertionError。

例如:

import unittest

class MyException(Exception): 
    pass

class MyUnitTest(unittest.TestCase):
    failureException = MyException

def add_one_to_int(a):
    assert isinstance(a, int)
    return a + 1


class TestAddOne(MyUnitTest):  # <--------- See above
    def test_one_plus_one_is_three(self):
        # This tests fails with
        #   AssertionError: 2 != 3
        # which is fine
        self.assertEqual(add_one_to_int(1), 3)  

    def test_add_one_to_str(self):
        # This tests fails with
        #   AssertionError
        # when I would rather have it an error
        add_one_to_int('some string')

if __name__ == '__main__':
    unittest.main(verbosity=2)  # ------> FAILED (failures=1, errors=1)