From d72afe7e08033c5e6268ec77f68e894fb1b6bab1 Mon Sep 17 00:00:00 2001 From: Dmitry Dygalo Date: Mon, 25 Jul 2016 10:54:02 +0200 Subject: [PATCH] Fixed scope override inside metafunc.parametrize. Fixes #634 --- CHANGELOG.rst | 4 ++++ _pytest/python.py | 10 ++++++++-- testing/python/metafunc.py | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c99947943..164fe18b6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -54,6 +54,10 @@ * Fixed collection of classes with custom ``__new__`` method. Fixes `#1579`_. Thanks to `@Stranger6667`_ for the PR. +* Fixed scope overriding inside metafunc.parametrize (`#634`_). + Thanks to `@Stranger6667`_ for the PR. + +.. _#634: https://github.com/pytest-dev/pytest/issues/634 .. _#1579: https://github.com/pytest-dev/pytest/issues/1579 .. _#1580: https://github.com/pytest-dev/pytest/pull/1580 .. _#1605: https://github.com/pytest-dev/pytest/issues/1605 diff --git a/_pytest/python.py b/_pytest/python.py index 812adf4b4..693d7c8c5 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1005,9 +1005,15 @@ class Metafunc(FuncargnamesCompatAttr): newmarks = newkeywords.setdefault(0, {}) newmarks[newmark.markname] = newmark - if scope is None: - scope = "function" + if self._arg2fixturedefs: + # Takes the most narrow scope from used fixtures + fixtures_scopes = [fixturedef[0].scope for fixturedef in self._arg2fixturedefs.values()] + for scope in reversed(scopes): + if scope in fixtures_scopes: + break + else: + scope = 'function' scopenum = scopes.index(scope) valtypes = {} for arg in argnames: diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 13c709579..d6e45384d 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -819,6 +819,43 @@ class TestMetafuncFunctional: reprec = testdir.inline_run() reprec.assertoutcome(passed=5) + def test_parametrize_issue634(self, testdir): + testdir.makepyfile(''' + import pytest + + @pytest.fixture(scope='module') + def foo(request): + print('preparing foo-%d' % request.param) + return 'foo-%d' % request.param + + + def test_one(foo): + pass + + + def test_two(foo): + pass + + + test_two.test_with = (2, 3) + + + def pytest_generate_tests(metafunc): + params = (1, 2, 3, 4) + if not 'foo' in metafunc.fixturenames: + return + + test_with = getattr(metafunc.function, 'test_with', None) + if test_with: + params = test_with + metafunc.parametrize('foo', params, indirect=True) + + ''') + result = testdir.runpytest("-s") + output = result.stdout.str() + assert output.count('preparing foo-2') == 1 + assert output.count('preparing foo-3') == 1 + def test_parametrize_issue323(self, testdir): testdir.makepyfile(""" import pytest