review feedback
This commit is contained in:
parent
13add4df43
commit
95cb7fb676
|
@ -1,3 +1 @@
|
||||||
New `require_plugins` configuration option allows the user to specify a list of plugins required for pytest to run. Warnings are raised if these plugins are not found when running pytest.
|
New `required_plugins` configuration option allows the user to specify a list of plugins required for pytest to run. An error is raised if any required plugins are not found when running pytest.
|
||||||
|
|
||||||
The `--strict-config` flag can be used to treat these warnings as errors.
|
|
||||||
|
|
|
@ -1561,16 +1561,15 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||||
See :ref:`change naming conventions` for more detailed examples.
|
See :ref:`change naming conventions` for more detailed examples.
|
||||||
|
|
||||||
|
|
||||||
.. confval:: require_plugins
|
.. confval:: required_plugins
|
||||||
|
|
||||||
A space separated list of plugins that must be present for pytest to run.
|
A space separated list of plugins that must be present for pytest to run.
|
||||||
If any one of the plugins is not found, emit a warning.
|
If any one of the plugins is not found, emit a error.
|
||||||
If pytest is run with ``--strict-config`` exceptions are raised in place of warnings.
|
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
[pytest]
|
[pytest]
|
||||||
require_plugins = html xdist
|
required_plugins = pytest-html pytest-xdist
|
||||||
|
|
||||||
|
|
||||||
.. confval:: testpaths
|
.. confval:: testpaths
|
||||||
|
|
|
@ -953,7 +953,7 @@ class Config:
|
||||||
self._parser.addini("addopts", "extra command line options", "args")
|
self._parser.addini("addopts", "extra command line options", "args")
|
||||||
self._parser.addini("minversion", "minimally required pytest version")
|
self._parser.addini("minversion", "minimally required pytest version")
|
||||||
self._parser.addini(
|
self._parser.addini(
|
||||||
"require_plugins",
|
"required_plugins",
|
||||||
"plugins that must be present for pytest to run",
|
"plugins that must be present for pytest to run",
|
||||||
type="args",
|
type="args",
|
||||||
default=[],
|
default=[],
|
||||||
|
@ -1090,11 +1090,21 @@ class Config:
|
||||||
self._emit_warning_or_fail("Unknown config ini key: {}\n".format(key))
|
self._emit_warning_or_fail("Unknown config ini key: {}\n".format(key))
|
||||||
|
|
||||||
def _validate_plugins(self) -> None:
|
def _validate_plugins(self) -> None:
|
||||||
for plugin in self.getini("require_plugins"):
|
plugin_info = self.pluginmanager.list_plugin_distinfo()
|
||||||
if not self.pluginmanager.hasplugin(plugin):
|
plugin_dist_names = [
|
||||||
self._emit_warning_or_fail(
|
"{dist.project_name}".format(dist=dist) for _, dist in plugin_info
|
||||||
"Missing required plugin: {}\n".format(plugin)
|
]
|
||||||
)
|
|
||||||
|
required_plugin_list = []
|
||||||
|
for plugin in sorted(self.getini("required_plugins")):
|
||||||
|
if plugin not in plugin_dist_names:
|
||||||
|
required_plugin_list.append(plugin)
|
||||||
|
|
||||||
|
if required_plugin_list:
|
||||||
|
fail(
|
||||||
|
"Missing required plugins: {}".format(", ".join(required_plugin_list)),
|
||||||
|
pytrace=False,
|
||||||
|
)
|
||||||
|
|
||||||
def _emit_warning_or_fail(self, message: str) -> None:
|
def _emit_warning_or_fail(self, message: str) -> None:
|
||||||
if self.known_args_namespace.strict_config:
|
if self.known_args_namespace.strict_config:
|
||||||
|
|
|
@ -213,51 +213,36 @@ class TestParseIni:
|
||||||
testdir.runpytest("--strict-config")
|
testdir.runpytest("--strict-config")
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"ini_file_text, stderr_output, exception_text",
|
"ini_file_text, exception_text",
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
"""
|
"""
|
||||||
[pytest]
|
[pytest]
|
||||||
require_plugins = fakePlugin1 fakePlugin2
|
required_plugins = fakePlugin1 fakePlugin2
|
||||||
""",
|
""",
|
||||||
[
|
"Missing required plugins: fakePlugin1, fakePlugin2",
|
||||||
"WARNING: Missing required plugin: fakePlugin1",
|
|
||||||
"WARNING: Missing required plugin: fakePlugin2",
|
|
||||||
],
|
|
||||||
"Missing required plugin: fakePlugin1",
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"""
|
"""
|
||||||
[pytest]
|
[pytest]
|
||||||
require_plugins = a monkeypatch z
|
required_plugins = a pytest-xdist z
|
||||||
""",
|
""",
|
||||||
[
|
"Missing required plugins: a, z",
|
||||||
"WARNING: Missing required plugin: a",
|
|
||||||
"WARNING: Missing required plugin: z",
|
|
||||||
],
|
|
||||||
"Missing required plugin: a",
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"""
|
"""
|
||||||
[pytest]
|
[pytest]
|
||||||
require_plugins = a monkeypatch z
|
required_plugins = a q j b c z
|
||||||
addopts = -p no:monkeypatch
|
|
||||||
""",
|
""",
|
||||||
[
|
"Missing required plugins: a, b, c, j, q, z",
|
||||||
"WARNING: Missing required plugin: a",
|
|
||||||
"WARNING: Missing required plugin: monkeypatch",
|
|
||||||
"WARNING: Missing required plugin: z",
|
|
||||||
],
|
|
||||||
"Missing required plugin: a",
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"""
|
"""
|
||||||
[some_other_header]
|
[some_other_header]
|
||||||
require_plugins = wont be triggered
|
required_plugins = wont be triggered
|
||||||
[pytest]
|
[pytest]
|
||||||
minversion = 5.0.0
|
minversion = 5.0.0
|
||||||
""",
|
""",
|
||||||
[],
|
|
||||||
"",
|
"",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -265,23 +250,21 @@ class TestParseIni:
|
||||||
[pytest]
|
[pytest]
|
||||||
minversion = 5.0.0
|
minversion = 5.0.0
|
||||||
""",
|
""",
|
||||||
[],
|
|
||||||
"",
|
"",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_missing_required_plugins(
|
def test_missing_required_plugins(self, testdir, ini_file_text, exception_text):
|
||||||
self, testdir, ini_file_text, stderr_output, exception_text
|
pytest.importorskip("xdist")
|
||||||
):
|
|
||||||
testdir.tmpdir.join("pytest.ini").write(textwrap.dedent(ini_file_text))
|
testdir.tmpdir.join("pytest.ini").write(textwrap.dedent(ini_file_text))
|
||||||
testdir.parseconfig()
|
testdir.monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD")
|
||||||
|
|
||||||
result = testdir.runpytest()
|
if exception_text:
|
||||||
result.stderr.fnmatch_lines(stderr_output)
|
|
||||||
|
|
||||||
if stderr_output:
|
|
||||||
with pytest.raises(pytest.fail.Exception, match=exception_text):
|
with pytest.raises(pytest.fail.Exception, match=exception_text):
|
||||||
testdir.runpytest("--strict-config")
|
testdir.parseconfig()
|
||||||
|
else:
|
||||||
|
testdir.parseconfig()
|
||||||
|
|
||||||
|
|
||||||
class TestConfigCmdlineParsing:
|
class TestConfigCmdlineParsing:
|
||||||
|
@ -681,6 +664,7 @@ def test_preparse_ordering_with_setuptools(testdir, monkeypatch):
|
||||||
|
|
||||||
class Dist:
|
class Dist:
|
||||||
files = ()
|
files = ()
|
||||||
|
metadata = {"name": "foo"}
|
||||||
entry_points = (EntryPoint(),)
|
entry_points = (EntryPoint(),)
|
||||||
|
|
||||||
def my_dists():
|
def my_dists():
|
||||||
|
@ -711,6 +695,7 @@ def test_setuptools_importerror_issue1479(testdir, monkeypatch):
|
||||||
class Distribution:
|
class Distribution:
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
files = ("foo.txt",)
|
files = ("foo.txt",)
|
||||||
|
metadata = {"name": "foo"}
|
||||||
entry_points = (DummyEntryPoint(),)
|
entry_points = (DummyEntryPoint(),)
|
||||||
|
|
||||||
def distributions():
|
def distributions():
|
||||||
|
@ -735,6 +720,7 @@ def test_importlib_metadata_broken_distribution(testdir, monkeypatch):
|
||||||
class Distribution:
|
class Distribution:
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
files = None
|
files = None
|
||||||
|
metadata = {"name": "foo"}
|
||||||
entry_points = (DummyEntryPoint(),)
|
entry_points = (DummyEntryPoint(),)
|
||||||
|
|
||||||
def distributions():
|
def distributions():
|
||||||
|
@ -760,6 +746,7 @@ def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch, block
|
||||||
class Distribution:
|
class Distribution:
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
files = ("foo.txt",)
|
files = ("foo.txt",)
|
||||||
|
metadata = {"name": "foo"}
|
||||||
entry_points = (DummyEntryPoint(),)
|
entry_points = (DummyEntryPoint(),)
|
||||||
|
|
||||||
def distributions():
|
def distributions():
|
||||||
|
@ -791,6 +778,7 @@ def test_disable_plugin_autoload(testdir, monkeypatch, parse_args, should_load):
|
||||||
return sys.modules[self.name]
|
return sys.modules[self.name]
|
||||||
|
|
||||||
class Distribution:
|
class Distribution:
|
||||||
|
metadata = {"name": "foo"}
|
||||||
entry_points = (DummyEntryPoint(),)
|
entry_points = (DummyEntryPoint(),)
|
||||||
files = ()
|
files = ()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue