Merge pull request #1620 from tomviner/issue460/parameterized-subrequest
Issue 460: Fail on getfuncargvalue(<fixture with params>)
This commit is contained in:
		
						commit
						c3ee1c17bc
					
				
							
								
								
									
										1
									
								
								AUTHORS
								
								
								
								
							
							
						
						
									
										1
									
								
								AUTHORS
								
								
								
								
							|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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)) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue