Raise an error if pytest_plugins is defined in a non-top-level conftest.py file

Fix #4548
This commit is contained in:
Bruno Oliveira 2018-12-19 18:09:47 -02:00
parent 9138419379
commit a93f41233a
5 changed files with 34 additions and 32 deletions

View File

@ -0,0 +1,3 @@
An error is now raised if the ``pytest_plugins`` variable is defined in a non-top-level ``conftest.py`` file (i.e., not residing in the ``rootdir``).
See our `docs <https://docs.pytest.org/en/latest/deprecations.html#pytest-plugins-in-non-top-level-conftest-files>`__ for more information.

View File

@ -81,16 +81,6 @@ As part of a large :ref:`marker-revamp`, :meth:`_pytest.nodes.Node.get_marker` i
:ref:`the documentation <update marker code>` on tips on how to update your code.
pytest_plugins in non-top-level conftest files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 3.5
Defining ``pytest_plugins`` is now deprecated in non-top-level conftest.py
files because they will activate referenced plugins *globally*, which is surprising because for all other pytest
features ``conftest.py`` files are only *active* for tests at or below it.
marks in ``pytest.mark.parametrize``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -242,6 +232,16 @@ You can consult `funcarg comparison section in the docs <https://docs.pytest.org
more information.
pytest_plugins in non-top-level conftest files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*Removed in version 4.0.*
Defining ``pytest_plugins`` is now deprecated in non-top-level conftest.py
files because they will activate referenced plugins *globally*, which is surprising because for all other pytest
features ``conftest.py`` files are only *active* for tests at or below it.
``Config.warn`` and ``Node.warn``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -31,6 +31,7 @@ from _pytest._code import ExceptionInfo
from _pytest._code import filter_traceback
from _pytest.compat import lru_cache
from _pytest.compat import safe_str
from _pytest.outcomes import fail
from _pytest.outcomes import Skipped
from _pytest.warning_types import PytestWarning
@ -429,11 +430,11 @@ class PytestPluginManager(PluginManager):
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
)
warnings.warn_explicit(
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST,
category=None,
filename=str(conftestpath),
lineno=0,
fail(
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST.format(
conftestpath, self._confcutdir
),
pytrace=False,
)
except Exception:
raise ConftestImportFailure(conftestpath, sys.exc_info())

View File

@ -69,10 +69,14 @@ WARNS_EXEC = PytestDeprecationWarning(
"See https://docs.pytest.org/en/latest/deprecations.html#raises-warns-exec"
)
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST = RemovedInPytest4Warning(
"Defining pytest_plugins in a non-top-level conftest is deprecated, "
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST = (
"Defining 'pytest_plugins' in a non-top-level conftest is no longer supported "
"because it affects the entire directory tree in a non-explicit way.\n"
"Please move it to the top level conftest file instead."
" {}\n"
"Please move it to a top level conftest file at the rootdir:\n"
" {}\n"
"For more information, visit:\n"
" https://docs.pytest.org/en/latest/deprecations.html#pytest-plugins-in-non-top-level-conftest-files"
)
PYTEST_CONFIG_GLOBAL = PytestDeprecationWarning(

View File

@ -113,17 +113,15 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated(testdir):
"""
)
res = testdir.runpytest(SHOW_PYTEST_WARNINGS_ARG)
assert res.ret == 0
assert res.ret == 2
msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
res.stdout.fnmatch_lines(
"*subdirectory{sep}conftest.py:0: RemovedInPytest4Warning: {msg}*".format(
sep=os.sep, msg=msg
)
["*{msg}*".format(msg=msg), "*subdirectory{sep}conftest.py*".format(sep=os.sep)]
)
@pytest.mark.parametrize("use_pyargs", [True, False])
def test_pytest_plugins_in_non_top_level_conftest_deprecated_pyargs(
def test_pytest_plugins_in_non_top_level_conftest_unsupported_pyargs(
testdir, use_pyargs
):
"""When using --pyargs, do not emit the warning about non-top-level conftest warnings (#4039, #4044)"""
@ -143,7 +141,7 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated_pyargs(
args = ("--pyargs", "pkg") if use_pyargs else ()
args += (SHOW_PYTEST_WARNINGS_ARG,)
res = testdir.runpytest(*args)
assert res.ret == 0
assert res.ret == (0 if use_pyargs else 2)
msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
if use_pyargs:
assert msg not in res.stdout.str()
@ -151,7 +149,7 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated_pyargs(
res.stdout.fnmatch_lines("*{msg}*".format(msg=msg))
def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_top_level_conftest(
def test_pytest_plugins_in_non_top_level_conftest_unsupported_no_top_level_conftest(
testdir
):
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
@ -160,8 +158,6 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_top_level_confte
subdirectory.mkdir()
testdir.makeconftest(
"""
import warnings
warnings.filterwarnings('always', category=DeprecationWarning)
pytest_plugins=['capture']
"""
)
@ -175,16 +171,14 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_top_level_confte
)
res = testdir.runpytest_subprocess()
assert res.ret == 0
assert res.ret == 2
msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
res.stdout.fnmatch_lines(
"*subdirectory{sep}conftest.py:0: RemovedInPytest4Warning: {msg}*".format(
sep=os.sep, msg=msg
)
["*{msg}*".format(msg=msg), "*subdirectory{sep}conftest.py*".format(sep=os.sep)]
)
def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_false_positives(
def test_pytest_plugins_in_non_top_level_conftest_unsupported_no_false_positives(
testdir
):
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST