从 pytest 夹具生成的工厂中产生
Yielding from a factory generated by a pytest fixture
下面的 pytest fixture
@pytest.fixture(scope="module")
def gen_factory():
def _gen_factory(owner: str):
value = ...
yield value
print('gen teardown')
yield _gen_factory
产生多次使用的工厂。
在测试用例中,我使用该夹具创建两个工厂并使用它们生成一些值:
@pytest.mark.asyncio
def test_case(gen_factory):
gen1 = gen_factory('owner1')
gen2 = gen_factory('owner2')
val1 = next(gen1)
val2 = next(gen2)
...
next(gen1)
next(gen2)
发生的情况是 print('gen teardown')
仅被调用一次,然后循环关闭,第二次 next()
调用引发 StopIteration
错误。
我在这里错过了什么?为什么第二次打印没有发生?
如果您不想更改夹具中的任何内容,只需将最后一次调用更改为 next
:
next(gen1, None)
使用默认值不会引发 StopIteration
。
另一种方法是使 _gen_factory
成为上下文管理器:
from contextlib import contextmanager
def gen_factory():
@contextmanager
def _gen_factory(owner):
value = owner
yield value
print('gen teardown')
yield _gen_factory
def test_case(genfactory):
with genfactory('owner1') as own1, genfactory('owner2') as own2:
print(own1, own2)
在执行最后一条语句 (next(gen2)
) 之前,错误发生在第二次调用 next(gen1)
的(最后一行)行上。迭代器已耗尽。这就是发电机的工作原理。 StopIteration
在生成器的末尾引发,(这就是打印第一个的原因!) 一旦它们没有要迭代的项目,除非传递默认值到内置 next
函数。 StopIteration
使 for 循环停止。尽管生成器可以以不同的方式使用,但它们的使用主要是在 for 循环中迭代。这就是为什么默认情况下会引发此 'exception'。
下面的 pytest fixture
@pytest.fixture(scope="module")
def gen_factory():
def _gen_factory(owner: str):
value = ...
yield value
print('gen teardown')
yield _gen_factory
产生多次使用的工厂。
在测试用例中,我使用该夹具创建两个工厂并使用它们生成一些值:
@pytest.mark.asyncio
def test_case(gen_factory):
gen1 = gen_factory('owner1')
gen2 = gen_factory('owner2')
val1 = next(gen1)
val2 = next(gen2)
...
next(gen1)
next(gen2)
发生的情况是 print('gen teardown')
仅被调用一次,然后循环关闭,第二次 next()
调用引发 StopIteration
错误。
我在这里错过了什么?为什么第二次打印没有发生?
如果您不想更改夹具中的任何内容,只需将最后一次调用更改为 next
:
next(gen1, None)
使用默认值不会引发 StopIteration
。
另一种方法是使 _gen_factory
成为上下文管理器:
from contextlib import contextmanager
def gen_factory():
@contextmanager
def _gen_factory(owner):
value = owner
yield value
print('gen teardown')
yield _gen_factory
def test_case(genfactory):
with genfactory('owner1') as own1, genfactory('owner2') as own2:
print(own1, own2)
在执行最后一条语句 (next(gen2)
) 之前,错误发生在第二次调用 next(gen1)
的(最后一行)行上。迭代器已耗尽。这就是发电机的工作原理。 StopIteration
在生成器的末尾引发,(这就是打印第一个的原因!) 一旦它们没有要迭代的项目,除非传递默认值到内置 next
函数。 StopIteration
使 for 循环停止。尽管生成器可以以不同的方式使用,但它们的使用主要是在 for 循环中迭代。这就是为什么默认情况下会引发此 'exception'。