测试函数在python中返回迭代

Tar*_*sch 8 python testing iterator

我在测试返回迭代的python函数时遇到了困难,比如正在产生的函数或只返回一个iterable的函数,比如return imap(f, some_iter)return permutations([1,2,3]).

因此,使用排列示例,我期望函数的输出[(1, 2, 3), (1, 3, 2), ...].所以,我开始测试我的代码.

def perm3():
  return permutations([1,2,3])

# Lets ignore test framework and such details
def test_perm3():
  assertEqual(perm3(), [(1, 2, 3), (1, 3, 2), ...])
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为perm3()它是可迭代的,而不是列表.所以我们可以解决这个特殊的例子.

def test_perm3():
  assertEqual(list(perm3()), [(1, 2, 3), (1, 3, 2), ...])
Run Code Online (Sandbox Code Playgroud)

这很好用.但是,如果我有嵌套的iterables怎么办?这是迭代产生迭代?喜欢说出表达方式 product(permutations([1, 2]), permutations([3, 4])).现在这可能没有用,但很明显它会(一旦展开迭代器)就像这样[((1, 2), (3, 4)), ((1, 2), (4, 3)), ...].然而,我们不能只是包装list围绕我们的结果,因为这只会反过来iterable<blah>[iterable<blah>, iterable<blah>, ...].当然,我可以这样做map(list, product(...)),但这仅适用于2的嵌套级别.

那么,python测试社区在测试iterables时是否有解决问题的方法?当然,有些迭代物不能以这种方式进行测试,就像你想要一个无限的发生器一样,但是这个问题应该是足够普遍的,以便有人想到这个.

unu*_*tbu 4

我使用KennyTM 的assertRecursiveEq

import unittest
import collections
import itertools

class TestCase(unittest.TestCase):
    def assertRecursiveEq(self, first, second, *args, **kwargs):
        """
        /sf/answers/218690881/ (KennyTM)
        """
        if (isinstance(first, collections.Iterable)
            and isinstance(second, collections.Iterable)):
            for first_, second_ in itertools.izip_longest(
                    first, second, fillvalue = object()):
                self.assertRecursiveEq(first_, second_, *args, **kwargs)
        else:
            # If first = np.nan and second = np.nan, I want them to
            # compare equal. np.isnan raises TypeErrors on some inputs,
            # so I use `first != first` as a proxy. I avoid dependency on numpy
            # as a bonus.
            if not (first != first and second != second):
                self.assertAlmostEqual(first, second, *args, **kwargs)                

def perm3():
    return itertools.permutations([1,2,3])

class Test(TestCase):
    def test_perm3(self):
        self.assertRecursiveEq(perm3(),
            [(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)])

if __name__ == '__main__':
    import sys
    sys.argv.insert(1, '--verbose')
    unittest.main(argv = sys.argv)
Run Code Online (Sandbox Code Playgroud)