我在使用生成器进行单元测试我正在使用的Python项目时遇到了问题。简化,项目/单元测试如下所示:
我有一个setUp()函数,用于创建Person实例。 Person是一个具有生成器next_task()的类,它生成Person所具有的下一个任务。
我现在有两个单元测试,使用for循环测试生成器工作方式的不同之处。第一次测试完全按照我的预期进行,第二次测试甚至从未进入循环。在两个单元测试中,第一行代码是:
for rank, task in enumerate(self.person.next_task()):
我的猜测是,这不起作用,因为在两个单独的单元测试中使用相同的生成器函数。但这似乎不是生成器或单元测试应该起作用的方式。我不应该在任务列表中迭代两次吗?此外,每个单元测试不应该使用一个本质上不同的Person实例,因为Person实例是在setUp()中创建的?
答案 0 :(得分:3)
如果您真的在setUp中创建一个新的Person对象,那么它应该按预期工作。有几个原因导致它可能无法正常工作:
1)您正在从另一个迭代器初始化Person的任务,并且在您第二次创建Person时就会耗尽。
2)每次创建一个新的Person对象,但是任务生成器是一个类变量而不是一个实例变量,因此在类实例之间共享。
3)您认为您正在创建一个新的Person对象,但实际上您并不是出于某种原因。也许它被实现为单身人士。
4)unittest setUp方法被破坏。
其中我认为(4)最不可能,但在我们追踪真正的问题之前,我们需要看到更多的代码。
答案 1 :(得分:0)
生成器的生成结果由使用它的第一个for
循环消耗。之后,生成器函数返回并结束 - 因此为空。由于第二个单元测试使用的是相同的生成器对象,因此它不会进入循环。您必须为第二个单元测试创建一个新的生成器,或者使用itertools.tee
从一个生成器中生成N个独立的迭代器。
发电机不按你想象的方式工作。每次调用generatorObject.next()
时,都会返回下一个产生的结果,但结果不会存储在任何位置。这就是为什么生成器经常用于惰性操作的原因。如果要重用结果,可以按照我的说法使用itertools.tee
,或将生成器转换为元组/结果列表。
使用文档中的itertools.tee
提示:
此itertool可能需要大量辅助存储(取决于需要存储多少临时数据)。通常,如果一个迭代器在另一个迭代器启动之前使用大部分或全部数据,则使用list()而不是tee()会更快。