Skip to content

Commit

Permalink
Merge pull request #1620 from tomviner/issue460/parameterized-subrequest
Browse files Browse the repository at this point in the history
Issue 460: Fail on getfuncargvalue(<fixture with params>)
  • Loading branch information
nicoddemus authored Jun 21, 2016
2 parents 61ede09 + 5854a71 commit c3ee1c1
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 2 deletions.
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
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))

0 comments on commit c3ee1c1

Please sign in to comment.