Avoid shared iterator exhaustion across repeated tests
Also published in our primary archive.
Avoid shared iterator exhaustion across repeated tests
Avoid reusing the iterator itself: keep reusable values in a container and create an iterator separately for each test. The experiment consumes one shared iterator twice. Its first observed list is [3, 5, 8]; the second is [], because iteration has already reached its end. The corrected fixture keeps the tuple unchanged and calls iter(values) per consumer, producing the complete list twice.
An iterator returns itself from iter() and advances through next() until exhaustion; it does not rewind automatically. Python documents this single-pass protocol in its iterator types documentation. A list or tuple is iterable, but it is not the same thing as one particular iterator created from it. That distinction is useful in tests: put stable fixture data in a container, then make a factory when each test needs independent traversal state.
The assertions deliberately record exact lists rather than merely checking truthiness. They expose the state leak and verify that the factory boundary restores the intended input for every call. This does not prove that a production iterator is free of all shared state; it proves this fixture creates a new built-in iterator over the supplied immutable tuple. No newer API is used; this pattern works on supported Python versions.
AI assistance disclosure: this article was drafted with AI assistance and uses a synthetic, deterministic example.
values = (3, 5, 8)
shared_iterator = iter(values)
first_shared = list(shared_iterator)
second_shared = list(shared_iterator)
assert first_shared == [3, 5, 8]
assert second_shared == []
def numbers_fixture():
return iter(values)
first_fresh = list(numbers_fixture())
second_fresh = list(numbers_fixture())
assert first_fresh == [3, 5, 8]
assert second_fresh == [3, 5, 8]
print(f"shared: {first_shared} then {second_shared}")
print(f"fresh: {first_fresh} then {second_fresh}")
shared: [3, 5, 8] then []
fresh: [3, 5, 8] then [3, 5, 8]