Merge pull request #1620 from tomviner/issue460/parameterized-subrequest

Issue 460: Fail on getfuncargvalue(<fixture with params>)
This commit is contained in:
Bruno Oliveira 2016-06-21 13:43:06 -03:00 committed by GitHub
commit c3ee1c17bc
4 changed files with 134 additions and 2 deletions

View File

@ -89,6 +89,7 @@ Ryan Wooden
Samuele Pedroni Samuele Pedroni
Simon Gomizelj Simon Gomizelj
Stefano Taschini Stefano Taschini
Stefan Farmbauer
Thomas Grainger Thomas Grainger
Tom Viner Tom Viner
Trevor Bekolay Trevor Bekolay

View File

@ -17,14 +17,21 @@
is specified on the command line together with the ``--pyargs`` is specified on the command line together with the ``--pyargs``
option. Thanks to `@taschini`_ for the PR (`#1597`_). 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 .. _#1580: https://github.com/pytest-dev/pytest/pull/1580
.. _#1605: https://github.com/pytest-dev/pytest/issues/1605 .. _#1605: https://github.com/pytest-dev/pytest/issues/1605
.. _#1597: https://github.com/pytest-dev/pytest/pull/1597 .. _#1597: https://github.com/pytest-dev/pytest/pull/1597
.. _#460: https://github.com/pytest-dev/pytest/pull/460
.. _@graingert: https://github.com/graingert .. _@graingert: https://github.com/graingert
.. _@taschini: https://github.com/taschini .. _@taschini: https://github.com/taschini
.. _@nikratio: https://github.com/nikratio
.. _@RedBeardCode: https://github.com/RedBeardCode
2.9.2 2.9.2

View File

@ -1651,6 +1651,25 @@ class FixtureRequest(FuncargnamesCompatAttr):
except (AttributeError, ValueError): except (AttributeError, ValueError):
param = NOTSET param = NOTSET
param_index = 0 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: else:
# indices might not be set if old-style metafunc.addcall() was used # indices might not be set if old-style metafunc.addcall() was used
param_index = funcitem.callspec.indices.get(argname, 0) param_index = funcitem.callspec.indices.get(argname, 0)

View File

@ -2723,3 +2723,108 @@ class TestContextManagerFixtureFuncs:
*def 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))