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

时间:2011-07-11 19:54:38

标签: python unit-testing

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

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

不幸的是,official documentation没有解释如何编写自定义断言方法。

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


我写的代码有点像这样:

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)

这种方法可以非常轻松地以非常紧凑的方式描述每个对象的预期值,而无需实际创建完整的对象。

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

3 个答案:

答案 0 :(得分:33)

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

首先。我定义了一个包含方法的类。

import os

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

现在我定义一个继承自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()

答案 1 :(得分:18)

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

答案 2 :(得分:1)

只是一个例子来总结一个numpy comparaison unittest

import numpy as np
class CustomTestCase(unittest.TestCase):
    def npAssertAlmostEqual(self, first, second, rtol=1e-06, atol=1e-08):
        np.testing.assert_allclose(first, second, rtol=rtol, atol=atol)


class TestVector(CustomTestCase):
    def testFunction(self):
        vx = np.random.rand(size)
        vy = np.random.rand(size)
        self.npAssertAlmostEqual(vx, vy)