deprecated pytest_plugins in non-top-level conftest
This commit is contained in:
parent
d6ddeb395b
commit
54b15f5826
|
@ -201,6 +201,8 @@ class PytestPluginManager(PluginManager):
|
|||
|
||||
# Config._consider_importhook will set a real object if required.
|
||||
self.rewrite_hook = _pytest.assertion.DummyRewriteHook()
|
||||
# Used to know when we are importing conftests after the pytest_configure stage
|
||||
self._configured = False
|
||||
|
||||
def addhooks(self, module_or_class):
|
||||
"""
|
||||
|
@ -276,6 +278,7 @@ class PytestPluginManager(PluginManager):
|
|||
config.addinivalue_line("markers",
|
||||
"trylast: mark a hook implementation function such that the "
|
||||
"plugin machinery will try to call it last/as late as possible.")
|
||||
self._configured = True
|
||||
|
||||
def _warn(self, message):
|
||||
kwargs = message if isinstance(message, dict) else {
|
||||
|
@ -366,6 +369,9 @@ class PytestPluginManager(PluginManager):
|
|||
_ensure_removed_sysmodule(conftestpath.purebasename)
|
||||
try:
|
||||
mod = conftestpath.pyimport()
|
||||
if hasattr(mod, 'pytest_plugins') and self._configured:
|
||||
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
|
||||
warnings.warn(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST)
|
||||
except Exception:
|
||||
raise ConftestImportFailure(conftestpath, sys.exc_info())
|
||||
|
||||
|
|
|
@ -56,3 +56,9 @@ METAFUNC_ADD_CALL = (
|
|||
"Metafunc.addcall is deprecated and scheduled to be removed in pytest 4.0.\n"
|
||||
"Please use Metafunc.parametrize instead."
|
||||
)
|
||||
|
||||
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST = RemovedInPytest4Warning(
|
||||
"Defining pytest_plugins in a non-top-level conftest is deprecated, "
|
||||
"because it affects the entire directory tree in a non-explicit way.\n"
|
||||
"Please move it to the top level conftest file instead."
|
||||
)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Defining ``pytest_plugins`` is now deprecated in non-top-level conftest.py files, because they "leak" to the entire directory tree.
|
|
@ -79,6 +79,12 @@ will be loaded as well.
|
|||
|
||||
which will import the specified module as a ``pytest`` plugin.
|
||||
|
||||
.. note::
|
||||
Requiring plugins using a ``pytest_plugins`` variable in non-root
|
||||
``conftest.py`` files is deprecated. See
|
||||
:ref:`full explanation <requiring plugins in non-noot conftests>`
|
||||
in the Writing plugins section.
|
||||
|
||||
.. _`findpluginname`:
|
||||
|
||||
Finding out which plugins are active
|
||||
|
|
|
@ -254,6 +254,18 @@ application modules:
|
|||
if ``myapp.testsupport.myplugin`` also declares ``pytest_plugins``, the contents
|
||||
of the variable will also be loaded as plugins, and so on.
|
||||
|
||||
.. _`requiring plugins in non-noot conftests`:
|
||||
|
||||
.. note::
|
||||
Requiring plugins using a ``pytest_plugins`` variable in non-root
|
||||
``conftest.py`` files is deprecated.
|
||||
|
||||
This is important because ``conftest.py`` files implement per-directory
|
||||
hook implementations, but once a plugin is imported, it will affect the
|
||||
entire directory tree. In order to avoid confusion, defining
|
||||
``pytest_plugins`` in any ``conftest.py`` file which is not located in the
|
||||
tests root directory is deprecated, and will raise a warning.
|
||||
|
||||
This mechanism makes it easy to share fixtures within applications or even
|
||||
external applications without the need to create external plugins using
|
||||
the ``setuptools``'s entry point technique.
|
||||
|
|
|
@ -134,3 +134,70 @@ def test_pytest_catchlog_deprecated(testdir, plugin):
|
|||
"*pytest-*log plugin has been merged into the core*",
|
||||
"*1 passed, 1 warnings*",
|
||||
])
|
||||
|
||||
|
||||
def test_pytest_plugins_in_non_top_level_conftest_deprecated(testdir):
|
||||
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
|
||||
subdirectory = testdir.tmpdir.join("subdirectory")
|
||||
subdirectory.mkdir()
|
||||
# create the inner conftest with makeconftest and then move it to the subdirectory
|
||||
testdir.makeconftest("""
|
||||
pytest_plugins=['capture']
|
||||
""")
|
||||
testdir.tmpdir.join("conftest.py").move(subdirectory.join("conftest.py"))
|
||||
# make the top level conftest
|
||||
testdir.makeconftest("""
|
||||
import warnings
|
||||
warnings.filterwarnings('always', category=DeprecationWarning)
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
res = testdir.runpytest_subprocess()
|
||||
assert res.ret == 0
|
||||
res.stderr.fnmatch_lines('*' + str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0])
|
||||
|
||||
|
||||
def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_top_level_conftest(testdir):
|
||||
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
|
||||
subdirectory = testdir.tmpdir.join('subdirectory')
|
||||
subdirectory.mkdir()
|
||||
testdir.makeconftest("""
|
||||
import warnings
|
||||
warnings.filterwarnings('always', category=DeprecationWarning)
|
||||
pytest_plugins=['capture']
|
||||
""")
|
||||
testdir.tmpdir.join("conftest.py").move(subdirectory.join("conftest.py"))
|
||||
|
||||
testdir.makepyfile("""
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
|
||||
res = testdir.runpytest_subprocess()
|
||||
assert res.ret == 0
|
||||
res.stderr.fnmatch_lines('*' + str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0])
|
||||
|
||||
|
||||
def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_false_positives(testdir):
|
||||
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
|
||||
subdirectory = testdir.tmpdir.join('subdirectory')
|
||||
subdirectory.mkdir()
|
||||
testdir.makeconftest("""
|
||||
pass
|
||||
""")
|
||||
testdir.tmpdir.join("conftest.py").move(subdirectory.join("conftest.py"))
|
||||
|
||||
testdir.makeconftest("""
|
||||
import warnings
|
||||
warnings.filterwarnings('always', category=DeprecationWarning)
|
||||
pytest_plugins=['capture']
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
res = testdir.runpytest_subprocess()
|
||||
assert res.ret == 0
|
||||
assert str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0] not in res.stderr.str()
|
||||
|
|
Loading…
Reference in New Issue