Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Python测试生成器_Python_Unit Testing_Python 3.x_Generator - Fatal编程技术网

用Python测试生成器

用Python测试生成器,python,unit-testing,python-3.x,generator,Python,Unit Testing,Python 3.x,Generator,我用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 sel

我用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)
当我使用for循环使用生成的值时,代码会起作用:

reader = Gen(...):
for v in reader.values():
   print(v)
但我现在尝试创建一个单元测试,为此,我需要一次获取每个值(在循环之外)。我正在尝试这样的事情:

import unittest
#...
reader = Gen(...):
v = reader.values()
self.assertIsNone(v)
当我尝试的时候,我总是得到一个

AssertionError: <generator object next_values at 0x7fe2a5f9e3f0> is not None
AssertionError:不是无
因此,当我自己调用值时,它会返回一些东西(是指针吗?)而不是生成的值


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

生成器需要迭代。您可以使用该函数获取生成器的下一个值。请注意,如果生成器已耗尽其值,它将引发异常

reader = Gen(...):
values = reader.values()
v = next(values)
self.assertIsNone(v)

我需要自己对一个生成器进行单元测试,所以我创建了这个助手函数:

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'

我需要检查生成器中的
返回产生的值是否有效,并且我需要知道当长度不同时产生的值与预期值之间的差异。我最终使用了一个相当大的helper函数,它可以读取多达6个生成但不是预期的值,或者反过来,并显示它们。这是:

从unittest导入TestCase
缺少类:
通过
def发生器测试仪(
自己
迭代器,
期望值列表,
预期\返回\值=缺失,
):
"""
测试生成器的辅助方法。
Args:
迭代器(迭代器):
要测试的生成器迭代器
期望值列表(列表):
生成器应生成的值的列表
预期\u返回的\u值(任意):
生成器返回的最终值
"""
期望值迭代器=iter(期望值列表)
尝试:
对于预期值迭代器中的预期值:
实际值=下一个(迭代器)
self.assertEqual(实际、预期)
除停止迭代外:
#生成器迭代器太短。
#
#len(迭代器)len(期望值迭代器)
#
#让我们看看生成器的额外值是什么
对于迭代器中的值:
剩余的_值。追加(值)
如果len(剩余_值)==8:
剩余_值[-1]=省略号
打破
self.fail(f“值太多:{剩余的值}”)

如果您希望类的实例是可移植的,您应该实现
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。除此之外,还有一个问题,
next\u value()
正在创建一个全新的生成器,而不是从现有生成器中为您提供下一个值(因此名称有点误导)。@jornsharpe明白了!我正在更改方法名称以反映您的重要观察结果。。。我把方法调用搞错了。谢谢但在这种情况下,我并不真正需要
\uuuu iter\uuuu
\uuuu next\uuuu
方法,因为
收益率一下子就给了我所有。你不一定需要
\uuu next\uuu
,但是如果你将方法重命名为
\uuuu iter\uuuu
,你就可以直接在实例上迭代,而不是显式地调用一个方法来进行迭代。虽然这可能会重复,但我怀疑OP希望实现
next(reader)
将生成
None
。哦,伙计!我想我已经试过了。无论如何,谢谢你@Brendan。令我感到奇怪的是,我找不到有关“”的任何信息。。。甚至连“dir(v)”都没有帮助!你能分享你的源代码吗?@Nigini[这里[()--我不能直接链接到页面中的点,但是在页面中搜索“生成器函数”。它们总是返回一个迭代器对象。你可以在该对象上调用
.next()
,以获取下一个值(或者使用内置的
next()
函数)。可能是python文档中可以更好地记录的内容之一。如何从生成器创建一个列表,然后根据您的期望进行检查?:
assert list(Gen(…)==[1,2,3,4]
问题是,生成器实际上可能不是生成器。可能返回了一个列表。
generator_tester(
    Gen(...),
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
)