Warn when a mark is applied to a fixture

Fixes #3664
This commit is contained in:
Thomas Grainger 2021-03-10 13:47:14 +00:00
parent 35df3e68d5
commit 3f71680ac0
No known key found for this signature in database
GPG Key ID: E452A1247BAC1A88
6 changed files with 30 additions and 2 deletions

View File

@ -0,0 +1 @@
Deprecate applying a mark to a fixture

View File

@ -1667,8 +1667,7 @@ into an ini-file:
def my_fixture_that_sadly_wont_use_my_other_fixture(): def my_fixture_that_sadly_wont_use_my_other_fixture():
... ...
Currently this will not generate any error or warning, but this is intended Currently this will generate a deprecation warning.
to be handled by `#3664 <https://github.com/pytest-dev/pytest/issues/3664>`_.
.. _`override fixtures`: .. _`override fixtures`:

View File

@ -95,6 +95,8 @@ NODE_FSPATH = UnformattedWarning(
"see https://docs.pytest.org/en/latest/deprecations.html#node-fspath-in-favor-of-pathlib-and-node-path", "see https://docs.pytest.org/en/latest/deprecations.html#node-fspath-in-favor-of-pathlib-and-node-path",
) )
MARKED_FIXTURE = PytestDeprecationWarning("Marks cannot be applied to fixtures")
# You want to make some `__init__` or function "private". # You want to make some `__init__` or function "private".
# #
# def my_private_function(some, args): # def my_private_function(some, args):

View File

@ -54,6 +54,7 @@ from _pytest.config import Config
from _pytest.config.argparsing import Parser from _pytest.config.argparsing import Parser
from _pytest.deprecated import check_ispytest from _pytest.deprecated import check_ispytest
from _pytest.deprecated import FILLFUNCARGS from _pytest.deprecated import FILLFUNCARGS
from _pytest.deprecated import MARKED_FIXTURE
from _pytest.deprecated import NODE_FSPATH from _pytest.deprecated import NODE_FSPATH
from _pytest.deprecated import YIELD_FIXTURE from _pytest.deprecated import YIELD_FIXTURE
from _pytest.mark import Mark from _pytest.mark import Mark
@ -1222,6 +1223,9 @@ class FixtureFunctionMarker:
"fixture is being applied more than once to the same function" "fixture is being applied more than once to the same function"
) )
if hasattr(function, "pytestmark"):
warnings.warn(MARKED_FIXTURE, stacklevel=2)
function = wrap_function_to_error_out_if_called_directly(function, self) function = wrap_function_to_error_out_if_called_directly(function, self)
name = self.name or function.__name__ name = self.name or function.__name__

View File

@ -29,6 +29,7 @@ from ..compat import NOTSET
from ..compat import NotSetType from ..compat import NotSetType
from _pytest.config import Config from _pytest.config import Config
from _pytest.deprecated import check_ispytest from _pytest.deprecated import check_ispytest
from _pytest.deprecated import MARKED_FIXTURE
from _pytest.outcomes import fail from _pytest.outcomes import fail
from _pytest.warning_types import PytestUnknownMarkWarning from _pytest.warning_types import PytestUnknownMarkWarning
@ -399,6 +400,9 @@ def store_mark(obj, mark: Mark) -> None:
assert isinstance(mark, Mark), mark assert isinstance(mark, Mark), mark
# Always reassign name to avoid updating pytestmark in a reference that # Always reassign name to avoid updating pytestmark in a reference that
# was only borrowed. # was only borrowed.
if hasattr(obj, "_pytestfixturefunction"):
warnings.warn(MARKED_FIXTURE, stacklevel=2)
obj.pytestmark = get_unpacked_marks(obj) + [mark] obj.pytestmark = get_unpacked_marks(obj) + [mark]

View File

@ -3612,6 +3612,24 @@ class TestShowFixtures:
def foo(): def foo():
raise NotImplementedError() raise NotImplementedError()
def test_fixture_disallow_on_marked_functions(self):
"""Test that applying @pytest.fixture to a marked function warns (#3364)."""
with pytest.warns(pytest.PytestDeprecationWarning):
@pytest.fixture
@pytest.mark.usefixtures("tmp_path")
def foo():
raise NotImplementedError()
def test_fixture_disallow_marks_on_fixtures(self):
"""Test that applying a mark to a fixture warns (#3364)."""
with pytest.warns(pytest.PytestDeprecationWarning):
@pytest.mark.usefixtures("tmp_path")
@pytest.fixture
def foo():
raise NotImplementedError()
class TestContextManagerFixtureFuncs: class TestContextManagerFixtureFuncs:
def test_simple(self, pytester: Pytester) -> None: def test_simple(self, pytester: Pytester) -> None: