测试包含浮点数的元组断言

7 投票
3 回答
7663 浏览
提问于 2025-04-15 23:51

我有一个函数,它返回一个元组,这个元组里包含了一个浮点数值。通常我会用 assertAlmostEquals 来比较这些浮点数,但这个方法不适用于元组。而且,这个元组里还有其他类型的数据。目前我是在逐个检查元组里的每个元素,但这样做对于一大堆这样的元组来说实在是太麻烦了。有没有什么好的方法可以写出这样的断言呢?

考虑这个函数:

def f(a):
    return [(1.0/x, x * 2) for x in a]

现在我想为它写一个测试:

def testF(self):
    self.assertEqual(f(range(1,3)), [(1.0, 2), (0.5, 4)])

这个测试会失败,因为 1.0/2 的结果并不完全等于 0.5。有没有人能推荐一种更好、更易读的方式来写这样的断言呢?

编辑:其实 1.0/2 确实是等于 0.5,不过你明白我的意思。

3 个回答

2

我过去做的事情是写一个自定义函数,用来检查一个复杂数据类型的有效性,然后使用 assert( IsFooValid( foo ) ) 来验证。这个有效性检查函数可以简单地返回真或假,但通常更好的是它能抛出一个AssertionError,并附上合适的错误信息。

3

我可能会定义一个递归函数。

from collections import Iterable;

def recursiveAssertAlmostEqual(testCase, first, second, *args, **kwargs):
   if isinstance(first, Iterable) and isinstance(second, Iterable):
      for a, b in zip(first, second):
         recursiveAssertAlmostEqual(testCase, a, b, *args, **kwargs)
   else:
      testCase.assertAlmostEqual(first, second, *args, **kwargs)

(注意,它会检查 (1, 2)[1, 2] 是否相等。)

8

那么,如何让你的函数更酷一些呢?可以试试用几个 zip:

def testF(self):
    for tuple1, tuple2 in zip(f(range(1,3)), [(1.0, 2), (0.5, 4)]):
        for val1, val2 in zip(tuple1, tuple2):
            if type(val2) is float:
                self.assertAlmostEquals(val1, val2, 5)
            else:
                self.assertEquals(val1, val2)

我的观点是,在循环中使用多个断言(assert)会更好,这样可以准确找到出错的具体值,而不是用一个断言配合 all()。

另外,如果你有其他数字类型想用 assertAlmostEquals 来检查,可以把上面的 if 改成,比如 if type(val2) in [float, decimal.Decimal]:

撰写回答