Skip to content

Commit de6c28e

Browse files
authored
Improve error handling around yieldctx fixtures which do not yield a value (#7083)
1 parent 9f4e680 commit de6c28e

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

changelog/7061.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
When a yielding fixture fails to yield a value, report a test setup error instead of crashing.

src/_pytest/fixtures.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -786,13 +786,18 @@ def fail_fixturefunc(fixturefunc, msg):
786786
def call_fixture_func(fixturefunc, request, kwargs):
787787
yieldctx = is_generator(fixturefunc)
788788
if yieldctx:
789-
it = fixturefunc(**kwargs)
790-
res = next(it)
791-
finalizer = functools.partial(_teardown_yield_fixture, fixturefunc, it)
789+
generator = fixturefunc(**kwargs)
790+
try:
791+
fixture_result = next(generator)
792+
except StopIteration:
793+
raise ValueError(
794+
"{} did not yield a value".format(request.fixturename)
795+
) from None
796+
finalizer = functools.partial(_teardown_yield_fixture, fixturefunc, generator)
792797
request.addfinalizer(finalizer)
793798
else:
794-
res = fixturefunc(**kwargs)
795-
return res
799+
fixture_result = fixturefunc(**kwargs)
800+
return fixture_result
796801

797802

798803
def _teardown_yield_fixture(fixturefunc, it):

testing/python/fixtures.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import pytest
55
from _pytest import fixtures
6+
from _pytest.config import ExitCode
67
from _pytest.fixtures import FixtureRequest
78
from _pytest.pathlib import Path
89
from _pytest.pytester import get_public_names
@@ -4290,3 +4291,23 @@ def test_suffix(fix_combined):
42904291
)
42914292
result = testdir.runpytest("-vv", str(p1))
42924293
assert result.ret == 0
4294+
4295+
4296+
def test_yield_fixture_with_no_value(testdir):
4297+
testdir.makepyfile(
4298+
"""
4299+
import pytest
4300+
@pytest.fixture(name='custom')
4301+
def empty_yield():
4302+
if False:
4303+
yield
4304+
4305+
def test_fixt(custom):
4306+
pass
4307+
"""
4308+
)
4309+
expected = "E ValueError: custom did not yield a value"
4310+
result = testdir.runpytest()
4311+
result.assert_outcomes(error=1)
4312+
result.stdout.fnmatch_lines([expected])
4313+
assert result.ret == ExitCode.TESTS_FAILED

0 commit comments

Comments
 (0)