Skip to content

Commit e5e91af

Browse files
committed
Issue 460: getfuncargvalue fixture w. params err
1 parent d81ee9a commit e5e91af

File tree

4 files changed

+133
-2
lines changed

4 files changed

+133
-2
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ Ryan Wooden
8989
Samuele Pedroni
9090
Simon Gomizelj
9191
Stefano Taschini
92+
Stefan Farmbauer
9293
Thomas Grainger
9394
Tom Viner
9495
Trevor Bekolay

CHANGELOG.rst

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Text documents without any doctests no longer appear as "skipped".
77
Thanks `@graingert`_ for reporting and providing a full PR (`#1580`_).
88

9-
* Fix internal error issue when ``method`` argument is missing for
9+
* Fix internal error issue when ``method`` argument is missing for
1010
``teardown_method()``. Fixes (`#1605`_).
1111

1212
* Fix exception visualization in case the current working directory (CWD) gets
@@ -17,14 +17,20 @@
1717
is specified on the command line together with the ``--pyargs``
1818
option. Thanks to `@taschini`_ for the PR (`#1597`_).
1919

20-
*
20+
* Raise helpful failure message, when requesting parametrized fixture at runtime,
21+
e.g. with ``request.getfuncargvalue``. BACKWARD INCOMPAT: Previously these params
22+
were simply never defined, now a failure is raised. Fixes (`#460`_). Thanks to
23+
`@nikratio`_ for bug report, `@RedBeardCode`_ and `@tomviner`_ for PR.
2124

2225
.. _#1580: https://github.com/pytest-dev/pytest/pull/1580
2326
.. _#1605: https://github.com/pytest-dev/pytest/issues/1605
2427
.. _#1597: https://github.com/pytest-dev/pytest/pull/1597
28+
.. _#460: https://github.com/pytest-dev/pytest/pull/460
2529

2630
.. _@graingert: https://github.com/graingert
2731
.. _@taschini: https://github.com/taschini
32+
.. _@nikratio: https://github.com/nikratio
33+
.. _@RedBeardCode: https://github.com/RedBeardCode
2834

2935

3036
2.9.2

_pytest/python.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,6 +1651,25 @@ def _getfuncargvalue(self, fixturedef):
16511651
except (AttributeError, ValueError):
16521652
param = NOTSET
16531653
param_index = 0
1654+
if fixturedef.params is not None:
1655+
frame = inspect.stack()[3]
1656+
frameinfo = inspect.getframeinfo(frame[0])
1657+
source_path = frameinfo.filename
1658+
source_lineno = frameinfo.lineno
1659+
source_path = py.path.local(source_path)
1660+
if source_path.relto(funcitem.config.rootdir):
1661+
source_path = source_path.relto(funcitem.config.rootdir)
1662+
msg = (
1663+
"The requested fixture has no parameter defined for the "
1664+
"current test.\n\nRequested fixture '{0}' defined in:\n{1}"
1665+
"\n\nRequested here:\n{2}:{3}".format(
1666+
fixturedef.argname,
1667+
getlocation(fixturedef.func, funcitem.config.rootdir),
1668+
source_path,
1669+
source_lineno,
1670+
)
1671+
)
1672+
pytest.fail(msg)
16541673
else:
16551674
# indices might not be set if old-style metafunc.addcall() was used
16561675
param_index = funcitem.callspec.indices.get(argname, 0)

testing/python/fixture.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2723,3 +2723,108 @@ def test_1(arg1):
27232723
*def arg1*
27242724
""")
27252725

2726+
class TestParameterizedSubRequest:
2727+
def test_call_from_fixture(self, testdir):
2728+
testfile = testdir.makepyfile("""
2729+
import pytest
2730+
2731+
@pytest.fixture(params=[0, 1, 2])
2732+
def fix_with_param(request):
2733+
return request.param
2734+
2735+
@pytest.fixture
2736+
def get_named_fixture(request):
2737+
return request.getfuncargvalue('fix_with_param')
2738+
2739+
def test_foo(request, get_named_fixture):
2740+
pass
2741+
""")
2742+
result = testdir.runpytest()
2743+
result.stdout.fnmatch_lines("""
2744+
E*Failed: The requested fixture has no parameter defined for the current test.
2745+
E*
2746+
E*Requested fixture 'fix_with_param' defined in:
2747+
E*{0}:4
2748+
E*Requested here:
2749+
E*{1}:9
2750+
*1 error*
2751+
""".format(testfile.basename, testfile.basename))
2752+
2753+
def test_call_from_test(self, testdir):
2754+
testfile = testdir.makepyfile("""
2755+
import pytest
2756+
2757+
@pytest.fixture(params=[0, 1, 2])
2758+
def fix_with_param(request):
2759+
return request.param
2760+
2761+
def test_foo(request):
2762+
request.getfuncargvalue('fix_with_param')
2763+
""")
2764+
result = testdir.runpytest()
2765+
result.stdout.fnmatch_lines("""
2766+
E*Failed: The requested fixture has no parameter defined for the current test.
2767+
E*
2768+
E*Requested fixture 'fix_with_param' defined in:
2769+
E*{0}:4
2770+
E*Requested here:
2771+
E*{1}:8
2772+
*1 failed*
2773+
""".format(testfile.basename, testfile.basename))
2774+
2775+
def test_external_fixture(self, testdir):
2776+
conffile = testdir.makeconftest("""
2777+
import pytest
2778+
2779+
@pytest.fixture(params=[0, 1, 2])
2780+
def fix_with_param(request):
2781+
return request.param
2782+
""")
2783+
2784+
testfile = testdir.makepyfile("""
2785+
def test_foo(request):
2786+
request.getfuncargvalue('fix_with_param')
2787+
""")
2788+
result = testdir.runpytest()
2789+
result.stdout.fnmatch_lines("""
2790+
E*Failed: The requested fixture has no parameter defined for the current test.
2791+
E*
2792+
E*Requested fixture 'fix_with_param' defined in:
2793+
E*{0}:4
2794+
E*Requested here:
2795+
E*{1}:2
2796+
*1 failed*
2797+
""".format(conffile.basename, testfile.basename))
2798+
2799+
def test_non_relative_path(self, testdir):
2800+
tests_dir = testdir.mkdir('tests')
2801+
fixdir = testdir.mkdir('fixtures')
2802+
fixfile = fixdir.join("fix.py")
2803+
fixfile.write(_pytest._code.Source("""
2804+
import pytest
2805+
2806+
@pytest.fixture(params=[0, 1, 2])
2807+
def fix_with_param(request):
2808+
return request.param
2809+
"""))
2810+
2811+
testfile = tests_dir.join("test_foos.py")
2812+
testfile.write(_pytest._code.Source("""
2813+
from fix import fix_with_param
2814+
2815+
def test_foo(request):
2816+
request.getfuncargvalue('fix_with_param')
2817+
"""))
2818+
2819+
tests_dir.chdir()
2820+
testdir.syspathinsert(fixdir)
2821+
result = testdir.runpytest()
2822+
result.stdout.fnmatch_lines("""
2823+
E*Failed: The requested fixture has no parameter defined for the current test.
2824+
E*
2825+
E*Requested fixture 'fix_with_param' defined in:
2826+
E*{0}:5
2827+
E*Requested here:
2828+
E*{1}:5
2829+
*1 failed*
2830+
""".format(fixfile.strpath, testfile.basename))

0 commit comments

Comments
 (0)