在 Python 中测试生成器

Nig*_*ini 7 python unit-testing generator python-3.x

我在 Python 3.4 中编写了一个非常简单的生成器:

class Gen:
  def __init__(self, xml_lines, attribs):
    #...

  def _get_values(self, xml_line):
    # get only specific "attribs" from a line in a "xml"

  def values(self):
    for line in self.xml_lines:
      yield self._get_values(line)
Run Code Online (Sandbox Code Playgroud)

当我使用 for 循环来使用生成的值时,代码有效:

reader = Gen(...):
for v in reader.values():
   print(v)
Run Code Online (Sandbox Code Playgroud)

但是我现在正在尝试创建一个单元测试,为此,我需要一次获取每个值(在循环之外)。我正在尝试这样的事情:

import unittest
#...
reader = Gen(...):
v = reader.values()
self.assertIsNone(v)
Run Code Online (Sandbox Code Playgroud)

当我尝试这样做时,我总是得到一个

AssertionError: <generator object next_values at 0x7fe2a5f9e3f0> is not None
Run Code Online (Sandbox Code Playgroud)

所以,当我自己调用这些值时,它返回一些东西(它是一个指针吗?)而不是生成的值。

当我考虑使用基本的生成器模式时,我的问题比我自己的代码更广泛:测试 Python 生成器的正确方法是什么?

Bre*_*bel 8

生成器旨在迭代。您可以使用next()函数来获取生成器的下一个值。请注意,如果您的生成器耗尽了它的值,它将引发StopIteration异常。

reader = Gen(...):
values = reader.values()
v = next(values)
self.assertIsNone(v)
Run Code Online (Sandbox Code Playgroud)


Sam*_*Sam 5

我需要自己对生成器进行单元测试,因此我创建了这个辅助函数:

def generator_tester(generator_iterator_to_test, expected_values):   
    range_index = 0
    for actual in generator_iterator_to_test:
        assert range_index + 1 <= len(expected_values), 'Too many values returned from range'
        assert expected_values[range_index] == actual
        range_index += 1

    assert range_index == len(expected_values), 'Too few values returned from range'
Run Code Online (Sandbox Code Playgroud)

这是使用它的示例:

generator_tester(
    Gen(...),
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
)
Run Code Online (Sandbox Code Playgroud)

  • 从生成器创建一个列表,然后根据您的期望检查它怎么样?: `assert list(Gen(...)) == [1, 2, 3, 4]` (4认同)