Skip to content

Issue 460: Fail on getfuncargvalue(<fixture with params>) #1620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ Ryan Wooden
Samuele Pedroni
Simon Gomizelj
Stefano Taschini
Stefan Farmbauer
Thomas Grainger
Tom Viner
Trevor Bekolay
Expand Down
11 changes: 9 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Text documents without any doctests no longer appear as "skipped".
Thanks `@graingert`_ for reporting and providing a full PR (`#1580`_).

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

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

*
* Raise helpful failure message, when requesting parametrized fixture at runtime,
e.g. with ``request.getfuncargvalue``. BACKWARD INCOMPAT: Previously these params
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed during the planning today, we would like to change that to getfixturevalue (keeping the older name only for backward compatibility). Would you like to do this in this PR? If not, would you please open a new issue? Thanks! 😁

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened #1625

were simply never defined. So a fixture decorated like ``@pytest.fixture(params=[0, 1, 2])``
only ran once. Now a failure is raised. Fixes (`#460`_). Thanks to
`@nikratio`_ for bug report, `@RedBeardCode`_ and `@tomviner`_ for PR.

.. _#1580: https://github.com/pytest-dev/pytest/pull/1580
.. _#1605: https://github.com/pytest-dev/pytest/issues/1605
.. _#1597: https://github.com/pytest-dev/pytest/pull/1597
.. _#460: https://github.com/pytest-dev/pytest/pull/460

.. _@graingert: https://github.com/graingert
.. _@taschini: https://github.com/taschini
.. _@nikratio: https://github.com/nikratio
.. _@RedBeardCode: https://github.com/RedBeardCode


2.9.2
Expand Down
19 changes: 19 additions & 0 deletions _pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -1651,6 +1651,25 @@ def _getfuncargvalue(self, fixturedef):
except (AttributeError, ValueError):
param = NOTSET
param_index = 0
if fixturedef.params is not None:
frame = inspect.stack()[3]
frameinfo = inspect.getframeinfo(frame[0])
source_path = frameinfo.filename
source_lineno = frameinfo.lineno
source_path = py.path.local(source_path)
if source_path.relto(funcitem.config.rootdir):
source_path = source_path.relto(funcitem.config.rootdir)
msg = (
"The requested fixture has no parameter defined for the "
"current test.\n\nRequested fixture '{0}' defined in:\n{1}"
"\n\nRequested here:\n{2}:{3}".format(
fixturedef.argname,
getlocation(fixturedef.func, funcitem.config.rootdir),
source_path,
source_lineno,
)
)
pytest.fail(msg)
else:
# indices might not be set if old-style metafunc.addcall() was used
param_index = funcitem.callspec.indices.get(argname, 0)
Expand Down
105 changes: 105 additions & 0 deletions testing/python/fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -2723,3 +2723,108 @@ def test_1(arg1):
*def arg1*
""")

class TestParameterizedSubRequest:
def test_call_from_fixture(self, testdir):
testfile = testdir.makepyfile("""
import pytest

@pytest.fixture(params=[0, 1, 2])
def fix_with_param(request):
return request.param

@pytest.fixture
def get_named_fixture(request):
return request.getfuncargvalue('fix_with_param')

def test_foo(request, get_named_fixture):
pass
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines("""
E*Failed: The requested fixture has no parameter defined for the current test.
E*
E*Requested fixture 'fix_with_param' defined in:
E*{0}:4
E*Requested here:
E*{1}:9
*1 error*
""".format(testfile.basename, testfile.basename))

def test_call_from_test(self, testdir):
testfile = testdir.makepyfile("""
import pytest

@pytest.fixture(params=[0, 1, 2])
def fix_with_param(request):
return request.param

def test_foo(request):
request.getfuncargvalue('fix_with_param')
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines("""
E*Failed: The requested fixture has no parameter defined for the current test.
E*
E*Requested fixture 'fix_with_param' defined in:
E*{0}:4
E*Requested here:
E*{1}:8
*1 failed*
""".format(testfile.basename, testfile.basename))

def test_external_fixture(self, testdir):
conffile = testdir.makeconftest("""
import pytest

@pytest.fixture(params=[0, 1, 2])
def fix_with_param(request):
return request.param
""")

testfile = testdir.makepyfile("""
def test_foo(request):
request.getfuncargvalue('fix_with_param')
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines("""
E*Failed: The requested fixture has no parameter defined for the current test.
E*
E*Requested fixture 'fix_with_param' defined in:
E*{0}:4
E*Requested here:
E*{1}:2
*1 failed*
""".format(conffile.basename, testfile.basename))

def test_non_relative_path(self, testdir):
tests_dir = testdir.mkdir('tests')
fixdir = testdir.mkdir('fixtures')
fixfile = fixdir.join("fix.py")
fixfile.write(_pytest._code.Source("""
import pytest

@pytest.fixture(params=[0, 1, 2])
def fix_with_param(request):
return request.param
"""))

testfile = tests_dir.join("test_foos.py")
testfile.write(_pytest._code.Source("""
from fix import fix_with_param

def test_foo(request):
request.getfuncargvalue('fix_with_param')
"""))

tests_dir.chdir()
testdir.syspathinsert(fixdir)
result = testdir.runpytest()
result.stdout.fnmatch_lines("""
E*Failed: The requested fixture has no parameter defined for the current test.
E*
E*Requested fixture 'fix_with_param' defined in:
E*{0}:5
E*Requested here:
E*{1}:5
*1 failed*
""".format(fixfile.strpath, testfile.basename))