Skip to content

Commit

Permalink
Merge pull request #2186 from nicoddemus/pytest-plugins-env-rewrite
Browse files Browse the repository at this point in the history
Consider plugins loaded by PYTEST_PLUGINS for assertion rewrite
  • Loading branch information
nicoddemus authored Jan 13, 2017
2 parents ff309b3 + 7cd7c28 commit 3dfdbaf
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 12 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
* pytest no longer recognizes coroutine functions as yield tests (`#2129`_).
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
expected warnings and the list of caught warnings is added to the
error message. Thanks `@lesteve`_ for the PR.
Expand All @@ -23,6 +27,7 @@
.. _#2129: https://github.com/pytest-dev/pytest/issues/2129
.. _#2148: https://github.com/pytest-dev/pytest/issues/2148
.. _#2150: https://github.com/pytest-dev/pytest/issues/2150
.. _#2185: https://github.com/pytest-dev/pytest/issues/2185


3.0.5 (2016-12-05)
Expand Down
35 changes: 24 additions & 11 deletions _pytest/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,31 +402,26 @@ def consider_env(self):
self._import_plugin_specs(os.environ.get("PYTEST_PLUGINS"))

def consider_module(self, mod):
plugins = getattr(mod, 'pytest_plugins', [])
if isinstance(plugins, str):
plugins = [plugins]
self.rewrite_hook.mark_rewrite(*plugins)
self._import_plugin_specs(plugins)
self._import_plugin_specs(getattr(mod, 'pytest_plugins', []))

def _import_plugin_specs(self, spec):
if spec:
if isinstance(spec, str):
spec = spec.split(",")
for import_spec in spec:
self.import_plugin(import_spec)
plugins = _get_plugin_specs_as_list(spec)
for import_spec in plugins:
self.import_plugin(import_spec)

def import_plugin(self, modname):
# most often modname refers to builtin modules, e.g. "pytester",
# "terminal" or "capture". Those plugins are registered under their
# basename for historic purposes but must be imported with the
# _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:
return
if modname in builtin_plugins:
importspec = "_pytest." + modname
else:
importspec = modname
self.rewrite_hook.mark_rewrite(modname)
try:
__import__(importspec)
except ImportError as e:
Expand All @@ -447,6 +442,24 @@ def import_plugin(self, modname):
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:
""" Parser for command line arguments and ini-file values.
Expand Down
18 changes: 17 additions & 1 deletion testing/test_assertrewrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ def test_remember_rewritten_modules(self, pytestconfig, testdir, monkeypatch):
hook.mark_rewrite('test_remember_rewritten_modules')
assert warnings == []

def test_rewrite_warning_using_pytest_plugins(self, testdir, monkeypatch):
def test_rewrite_warning_using_pytest_plugins(self, testdir):
testdir.makepyfile(**{
'conftest.py': "pytest_plugins = ['core', 'gui', 'sci']",
'core.py': "",
Expand All @@ -695,6 +695,22 @@ def test_rewrite_warning_using_pytest_plugins(self, testdir, monkeypatch):
result.stdout.fnmatch_lines(['*= 1 passed in *=*'])
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):
def test_loader_is_package_false_for_module(self, testdir):
Expand Down
15 changes: 15 additions & 0 deletions testing/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,21 @@ def pytest_load_initial_conftests(self):
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:
def test_warn_config(self, testdir):
testdir.makeconftest("""
Expand Down

0 comments on commit 3dfdbaf

Please sign in to comment.