Commit solution thus far, needs to be polished up pre PR
This commit is contained in:
parent
19ad588935
commit
2a3c21645e
|
@ -1604,3 +1604,13 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||||
|
|
||||||
[pytest]
|
[pytest]
|
||||||
xfail_strict = True
|
xfail_strict = True
|
||||||
|
|
||||||
|
|
||||||
|
.. confval:: required_plugins
|
||||||
|
|
||||||
|
A space seperated list of plugins that must be present for pytest to run
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[pytest]
|
||||||
|
require_plugins = pluginA pluginB pluginC
|
||||||
|
|
|
@ -952,6 +952,12 @@ class Config:
|
||||||
self._parser.extra_info["inifile"] = self.inifile
|
self._parser.extra_info["inifile"] = self.inifile
|
||||||
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(
|
||||||
|
"require_plugins",
|
||||||
|
"plugins that must be present for pytest to run",
|
||||||
|
type="args",
|
||||||
|
default=[],
|
||||||
|
)
|
||||||
self._override_ini = ns.override_ini or ()
|
self._override_ini = ns.override_ini or ()
|
||||||
|
|
||||||
def _consider_importhook(self, args: Sequence[str]) -> None:
|
def _consider_importhook(self, args: Sequence[str]) -> None:
|
||||||
|
@ -1035,7 +1041,8 @@ class Config:
|
||||||
self.known_args_namespace = ns = self._parser.parse_known_args(
|
self.known_args_namespace = ns = self._parser.parse_known_args(
|
||||||
args, namespace=copy.copy(self.option)
|
args, namespace=copy.copy(self.option)
|
||||||
)
|
)
|
||||||
self._validatekeys()
|
self._validate_keys()
|
||||||
|
self._validate_plugins()
|
||||||
if self.known_args_namespace.confcutdir is None and self.inifile:
|
if self.known_args_namespace.confcutdir is None and self.inifile:
|
||||||
confcutdir = py.path.local(self.inifile).dirname
|
confcutdir = py.path.local(self.inifile).dirname
|
||||||
self.known_args_namespace.confcutdir = confcutdir
|
self.known_args_namespace.confcutdir = confcutdir
|
||||||
|
@ -1078,9 +1085,23 @@ class Config:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def _validatekeys(self):
|
def _validate_keys(self) -> None:
|
||||||
for key in sorted(self._get_unknown_ini_keys()):
|
for key in sorted(self._get_unknown_ini_keys()):
|
||||||
message = "Unknown config ini key: {}\n".format(key)
|
self._emit_warning_or_fail("Unknown config ini key: {}\n".format(key))
|
||||||
|
|
||||||
|
def _validate_plugins(self) -> None:
|
||||||
|
# so iterate over all required plugins and see if pluginmanager hasplugin
|
||||||
|
# NOTE: This also account for -p no:<plugin> ( e.g: -p no:celery )
|
||||||
|
# raise ValueError(self._parser._inidict['requiredplugins'])
|
||||||
|
# raise ValueError(self.getini("requiredplugins"))
|
||||||
|
# raise ValueError(self.pluginmanager.hasplugin('debugging'))
|
||||||
|
for plugin in self.getini("require_plugins"):
|
||||||
|
if not self.pluginmanager.hasplugin(plugin):
|
||||||
|
self._emit_warning_or_fail(
|
||||||
|
"Missing required plugin: {}\n".format(plugin)
|
||||||
|
)
|
||||||
|
|
||||||
|
def _emit_warning_or_fail(self, message: str) -> None:
|
||||||
if self.known_args_namespace.strict_config:
|
if self.known_args_namespace.strict_config:
|
||||||
fail(message, pytrace=False)
|
fail(message, pytrace=False)
|
||||||
sys.stderr.write("WARNING: {}".format(message))
|
sys.stderr.write("WARNING: {}".format(message))
|
||||||
|
|
|
@ -212,6 +212,77 @@ class TestParseIni:
|
||||||
with pytest.raises(pytest.fail.Exception, match=exception_text):
|
with pytest.raises(pytest.fail.Exception, match=exception_text):
|
||||||
testdir.runpytest("--strict-config")
|
testdir.runpytest("--strict-config")
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"ini_file_text, stderr_output, exception_text",
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"""
|
||||||
|
[pytest]
|
||||||
|
require_plugins = fakePlugin1 fakePlugin2
|
||||||
|
""",
|
||||||
|
[
|
||||||
|
"WARNING: Missing required plugin: fakePlugin1",
|
||||||
|
"WARNING: Missing required plugin: fakePlugin2",
|
||||||
|
],
|
||||||
|
"Missing required plugin: fakePlugin1",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"""
|
||||||
|
[pytest]
|
||||||
|
require_plugins = a monkeypatch z
|
||||||
|
""",
|
||||||
|
[
|
||||||
|
"WARNING: Missing required plugin: a",
|
||||||
|
"WARNING: Missing required plugin: z",
|
||||||
|
],
|
||||||
|
"Missing required plugin: a",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"""
|
||||||
|
[pytest]
|
||||||
|
require_plugins = a monkeypatch z
|
||||||
|
addopts = -p no:monkeypatch
|
||||||
|
""",
|
||||||
|
[
|
||||||
|
"WARNING: Missing required plugin: a",
|
||||||
|
"WARNING: Missing required plugin: monkeypatch",
|
||||||
|
"WARNING: Missing required plugin: z",
|
||||||
|
],
|
||||||
|
"Missing required plugin: a",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"""
|
||||||
|
[some_other_header]
|
||||||
|
require_plugins = wont be triggered
|
||||||
|
[pytest]
|
||||||
|
minversion = 5.0.0
|
||||||
|
""",
|
||||||
|
[],
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"""
|
||||||
|
[pytest]
|
||||||
|
minversion = 5.0.0
|
||||||
|
""",
|
||||||
|
[],
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_missing_required_plugins(
|
||||||
|
self, testdir, ini_file_text, stderr_output, exception_text
|
||||||
|
):
|
||||||
|
testdir.tmpdir.join("pytest.ini").write(textwrap.dedent(ini_file_text))
|
||||||
|
testdir.parseconfig()
|
||||||
|
|
||||||
|
result = testdir.runpytest()
|
||||||
|
result.stderr.fnmatch_lines(stderr_output)
|
||||||
|
|
||||||
|
if stderr_output:
|
||||||
|
with pytest.raises(pytest.fail.Exception, match=exception_text):
|
||||||
|
testdir.runpytest("--strict-config")
|
||||||
|
|
||||||
|
|
||||||
class TestConfigCmdlineParsing:
|
class TestConfigCmdlineParsing:
|
||||||
def test_parsing_again_fails(self, testdir):
|
def test_parsing_again_fails(self, testdir):
|
||||||
|
|
Loading…
Reference in New Issue