如何在Python中编写自定义`.assertFoo()`方法?

Den*_*aia 36 python unit-testing

我正在使用Python为我的应用程序编写一些测试用例unittest.现在我需要将一个对象列表与另一个对象列表进行比较,以检查第一个列表中的对象是否是我所期望的.

如何编写自定义.assertFoo()方法?它该怎么办?它应该在失败时引发异常吗?如果是,哪个例外?以及如何传递错误信息?错误消息应该是unicode字符串还是字节串?

不幸的是,官方文档没有解释如何编写自定义断言方法.

如果你需要一个真实的例子,继续阅读.


我写的代码有点像这样:

def assert_object_list(self, objs, expected):
    for index, (item, values) in enumerate(zip(objs, expected)):
        self.assertEqual(
            item.foo, values[0],
            'Item {0}: {1} != {2}'.format(index, item.foo, values[0])
        )
        self.assertEqual(
            item.bar, values[1],
            'Item {0}: {1} != {2}'.format(index, item.bar, values[1])
        )

def test_foobar(self):
    objs = [...]  # Some processing here
    expected = [
        # Expected values for ".foo" and ".bar" for each object
        (1, 'something'),
        (2, 'nothing'),
    ]
    self.assert_object_list(objs, expected)
Run Code Online (Sandbox Code Playgroud)

这种方法使得以非常紧凑的方式描述每个对象的期望值非常容易,并且无需实际创建完整对象.

但是......当一个对象未​​通过断言时,不会比较其他对象,这会使调试变得更加困难.我想编写一个自定义方法,无条件地比较所有对象,然后显示所有失败的对象,而不是只显示第一个.

Ala*_*ian 35

我在这些情况下使用多重继承.例如:

第一.我定义了一个包含方法的类.

import os

class CustomAssertions:
    def assertFileExists(self, path):
        if not os.path.lexists(path):
            raise AssertionError('File not exists in path "' + path + '".')
Run Code Online (Sandbox Code Playgroud)

现在我定义一个继承自unittest.TestCase和CustomAssertion的类

import unittest

class MyTest(unittest.TestCase, CustomAssertions):
    def test_file_exists(self):
        self.assertFileExists('any/file/path')

if __name__ == '__main__':
    unittest.main()
Run Code Online (Sandbox Code Playgroud)

  • 这种方法也称为[mixin](https://en.wikipedia.org/wiki/Mixin#In_Python). (8认同)
  • 子类化的好替代方法 - 这很有帮助. (3认同)
  • @CristóbalGanter 修复堆栈跟踪中的行,请参阅 /sf/ask/3494951071/#49929579 (3认同)
  • 我做了类似的事情,但是我认为很烦人的是,当测试失败时,堆栈跟踪始终显示您引发断言错误的行,而不是实际测试中调用断言函数的行。有办法解决吗? (2认同)
  • 推荐测试失败信号的方法是调用 `self.fail()` 或等效的 `raise self.failureException(msg)`。虽然 raise 和 AssertionError 现在可以工作,但 unittest 框架可能并不总是对其进行等效处理:请参阅 https://docs.python.org/2/library/unittest.html#re-using-old-test-code (2认同)

Ned*_*der 18

您应该创建自己的TestCase类,派生自unittest.TestCase.然后将自定义断言方法放入该测试用例类中.如果测试失败,请引发AssertionError.您的消息应该是一个字符串.如果要测试列表中的所有对象而不是停止失败,则收集失败索引的列表,并在遍历所有对象之后,构建一个汇总消息,总结您的发现.