Merge pull request #2186 from nicoddemus/pytest-plugins-env-rewrite
Consider plugins loaded by PYTEST_PLUGINS for assertion rewrite
This commit is contained in:
commit
3dfdbaf490
|
@ -6,6 +6,10 @@
|
||||||
* pytest no longer recognizes coroutine functions as yield tests (`#2129`_).
|
* pytest no longer recognizes coroutine functions as yield tests (`#2129`_).
|
||||||
Thanks to `@malinoff`_ for the PR.
|
Thanks to `@malinoff`_ for the PR.
|
||||||
|
|
||||||
|
* Plugins loaded by the ``PYTEST_PLUGINS`` environment variable are now automatically
|
||||||
|
considered for assertion rewriting (`#2185`_).
|
||||||
|
Thanks `@nicoddemus`_ for the PR.
|
||||||
|
|
||||||
* Improve error message when pytest.warns fails (`#2150`_). The type(s) of the
|
* Improve error message when pytest.warns fails (`#2150`_). The type(s) of the
|
||||||
expected warnings and the list of caught warnings is added to the
|
expected warnings and the list of caught warnings is added to the
|
||||||
error message. Thanks `@lesteve`_ for the PR.
|
error message. Thanks `@lesteve`_ for the PR.
|
||||||
|
@ -23,6 +27,7 @@
|
||||||
.. _#2129: https://github.com/pytest-dev/pytest/issues/2129
|
.. _#2129: https://github.com/pytest-dev/pytest/issues/2129
|
||||||
.. _#2148: https://github.com/pytest-dev/pytest/issues/2148
|
.. _#2148: https://github.com/pytest-dev/pytest/issues/2148
|
||||||
.. _#2150: https://github.com/pytest-dev/pytest/issues/2150
|
.. _#2150: https://github.com/pytest-dev/pytest/issues/2150
|
||||||
|
.. _#2185: https://github.com/pytest-dev/pytest/issues/2185
|
||||||
|
|
||||||
|
|
||||||
3.0.5 (2016-12-05)
|
3.0.5 (2016-12-05)
|
||||||
|
|
|
@ -402,31 +402,26 @@ class PytestPluginManager(PluginManager):
|
||||||
self._import_plugin_specs(os.environ.get("PYTEST_PLUGINS"))
|
self._import_plugin_specs(os.environ.get("PYTEST_PLUGINS"))
|
||||||
|
|
||||||
def consider_module(self, mod):
|
def consider_module(self, mod):
|
||||||
plugins = getattr(mod, 'pytest_plugins', [])
|
self._import_plugin_specs(getattr(mod, 'pytest_plugins', []))
|
||||||
if isinstance(plugins, str):
|
|
||||||
plugins = [plugins]
|
|
||||||
self.rewrite_hook.mark_rewrite(*plugins)
|
|
||||||
self._import_plugin_specs(plugins)
|
|
||||||
|
|
||||||
def _import_plugin_specs(self, spec):
|
def _import_plugin_specs(self, spec):
|
||||||
if spec:
|
plugins = _get_plugin_specs_as_list(spec)
|
||||||
if isinstance(spec, str):
|
for import_spec in plugins:
|
||||||
spec = spec.split(",")
|
self.import_plugin(import_spec)
|
||||||
for import_spec in spec:
|
|
||||||
self.import_plugin(import_spec)
|
|
||||||
|
|
||||||
def import_plugin(self, modname):
|
def import_plugin(self, modname):
|
||||||
# most often modname refers to builtin modules, e.g. "pytester",
|
# most often modname refers to builtin modules, e.g. "pytester",
|
||||||
# "terminal" or "capture". Those plugins are registered under their
|
# "terminal" or "capture". Those plugins are registered under their
|
||||||
# basename for historic purposes but must be imported with the
|
# basename for historic purposes but must be imported with the
|
||||||
# _pytest prefix.
|
# _pytest prefix.
|
||||||
assert isinstance(modname, str)
|
assert isinstance(modname, str), "module name as string required, got %r" % modname
|
||||||
if self.get_plugin(modname) is not None:
|
if self.get_plugin(modname) is not None:
|
||||||
return
|
return
|
||||||
if modname in builtin_plugins:
|
if modname in builtin_plugins:
|
||||||
importspec = "_pytest." + modname
|
importspec = "_pytest." + modname
|
||||||
else:
|
else:
|
||||||
importspec = modname
|
importspec = modname
|
||||||
|
self.rewrite_hook.mark_rewrite(modname)
|
||||||
try:
|
try:
|
||||||
__import__(importspec)
|
__import__(importspec)
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
|
@ -447,6 +442,24 @@ class PytestPluginManager(PluginManager):
|
||||||
self.consider_module(mod)
|
self.consider_module(mod)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_plugin_specs_as_list(specs):
|
||||||
|
"""
|
||||||
|
Parses a list of "plugin specs" and returns a list of plugin names.
|
||||||
|
|
||||||
|
Plugin specs can be given as a list of strings separated by "," or already as a list/tuple in
|
||||||
|
which case it is returned as a list. Specs can also be `None` in which case an
|
||||||
|
empty list is returned.
|
||||||
|
"""
|
||||||
|
if specs is not None:
|
||||||
|
if isinstance(specs, str):
|
||||||
|
specs = specs.split(',') if specs else []
|
||||||
|
if not isinstance(specs, (list, tuple)):
|
||||||
|
raise UsageError("Plugin specs must be a ','-separated string or a "
|
||||||
|
"list/tuple of strings for plugin names. Given: %r" % specs)
|
||||||
|
return list(specs)
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
class Parser:
|
class Parser:
|
||||||
""" Parser for command line arguments and ini-file values.
|
""" Parser for command line arguments and ini-file values.
|
||||||
|
|
||||||
|
|
|
@ -682,7 +682,7 @@ def test_rewritten():
|
||||||
hook.mark_rewrite('test_remember_rewritten_modules')
|
hook.mark_rewrite('test_remember_rewritten_modules')
|
||||||
assert warnings == []
|
assert warnings == []
|
||||||
|
|
||||||
def test_rewrite_warning_using_pytest_plugins(self, testdir, monkeypatch):
|
def test_rewrite_warning_using_pytest_plugins(self, testdir):
|
||||||
testdir.makepyfile(**{
|
testdir.makepyfile(**{
|
||||||
'conftest.py': "pytest_plugins = ['core', 'gui', 'sci']",
|
'conftest.py': "pytest_plugins = ['core', 'gui', 'sci']",
|
||||||
'core.py': "",
|
'core.py': "",
|
||||||
|
@ -695,6 +695,22 @@ def test_rewritten():
|
||||||
result.stdout.fnmatch_lines(['*= 1 passed in *=*'])
|
result.stdout.fnmatch_lines(['*= 1 passed in *=*'])
|
||||||
assert 'pytest-warning summary' not in result.stdout.str()
|
assert 'pytest-warning summary' not in result.stdout.str()
|
||||||
|
|
||||||
|
def test_rewrite_warning_using_pytest_plugins_env_var(self, testdir, monkeypatch):
|
||||||
|
monkeypatch.setenv('PYTEST_PLUGINS', 'plugin')
|
||||||
|
testdir.makepyfile(**{
|
||||||
|
'plugin.py': "",
|
||||||
|
'test_rewrite_warning_using_pytest_plugins_env_var.py': """
|
||||||
|
import plugin
|
||||||
|
pytest_plugins = ['plugin']
|
||||||
|
def test():
|
||||||
|
pass
|
||||||
|
""",
|
||||||
|
})
|
||||||
|
testdir.chdir()
|
||||||
|
result = testdir.runpytest_subprocess()
|
||||||
|
result.stdout.fnmatch_lines(['*= 1 passed in *=*'])
|
||||||
|
assert 'pytest-warning summary' not in result.stdout.str()
|
||||||
|
|
||||||
|
|
||||||
class TestAssertionRewriteHookDetails(object):
|
class TestAssertionRewriteHookDetails(object):
|
||||||
def test_loader_is_package_false_for_module(self, testdir):
|
def test_loader_is_package_false_for_module(self, testdir):
|
||||||
|
|
|
@ -587,6 +587,21 @@ def test_load_initial_conftest_last_ordering(testdir):
|
||||||
assert [x.function.__module__ for x in l] == expected
|
assert [x.function.__module__ for x in l] == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_plugin_specs_as_list():
|
||||||
|
from _pytest.config import _get_plugin_specs_as_list
|
||||||
|
with pytest.raises(pytest.UsageError):
|
||||||
|
_get_plugin_specs_as_list(set(['foo']))
|
||||||
|
with pytest.raises(pytest.UsageError):
|
||||||
|
_get_plugin_specs_as_list(dict())
|
||||||
|
|
||||||
|
assert _get_plugin_specs_as_list(None) == []
|
||||||
|
assert _get_plugin_specs_as_list('') == []
|
||||||
|
assert _get_plugin_specs_as_list('foo') == ['foo']
|
||||||
|
assert _get_plugin_specs_as_list('foo,bar') == ['foo', 'bar']
|
||||||
|
assert _get_plugin_specs_as_list(['foo', 'bar']) == ['foo', 'bar']
|
||||||
|
assert _get_plugin_specs_as_list(('foo', 'bar')) == ['foo', 'bar']
|
||||||
|
|
||||||
|
|
||||||
class TestWarning:
|
class TestWarning:
|
||||||
def test_warn_config(self, testdir):
|
def test_warn_config(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
|
|
Loading…
Reference in New Issue