refine plugin registration, allow new "-p no:NAME" way to prevent/undo plugin registration

This commit is contained in:
holger krekel 2010-12-06 16:54:42 +01:00
parent 752965c298
commit c7531705fc
17 changed files with 169 additions and 102 deletions

View File

@ -1,7 +1,11 @@
Changes between 2.0.0 and 2.0.1.dev1 Changes between 2.0.0 and 2.0.1.dev1
---------------------------------------------- ----------------------------------------------
- refinements to terminal output - refinements to "collecting" output on non-ttys
- refine internal plugin registration and --traceconfig output
- introduce a mechanism to prevent/unregister plugins from the
command line, see http://pytest.org/plugins.html#cmdunregister
- activate resultlog plugin by default
Changes between 1.3.4 and 2.0.0 Changes between 1.3.4 and 2.0.0
---------------------------------------------- ----------------------------------------------

View File

@ -300,9 +300,9 @@ class Config(object):
if addopts: if addopts:
args[:] = self.getini("addopts") + args args[:] = self.getini("addopts") + args
self._checkversion() self._checkversion()
self.pluginmanager.consider_preparse(args)
self.pluginmanager.consider_setuptools_entrypoints() self.pluginmanager.consider_setuptools_entrypoints()
self.pluginmanager.consider_env() self.pluginmanager.consider_env()
self.pluginmanager.consider_preparse(args)
self._setinitialconftest(args) self._setinitialconftest(args)
self.pluginmanager.do_addoption(self._parser) self.pluginmanager.do_addoption(self._parser)

View File

@ -11,11 +11,9 @@ assert py.__version__.split(".")[:2] >= ['1', '4'], ("installation problem: "
"%s is too old, remove or upgrade 'py'" % (py.__version__)) "%s is too old, remove or upgrade 'py'" % (py.__version__))
default_plugins = ( default_plugins = (
"config mark session terminal runner python pdb unittest capture skipping " "config mark main terminal runner python pdb unittest capture skipping "
"tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript " "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript "
"junitxml doctest").split() "junitxml resultlog doctest").split()
IMPORTPREFIX = "pytest_"
class TagTracer: class TagTracer:
def __init__(self, prefix="[pytest] "): def __init__(self, prefix="[pytest] "):
@ -79,20 +77,12 @@ class PluginManager(object):
for spec in default_plugins: for spec in default_plugins:
self.import_plugin(spec) self.import_plugin(spec)
def _getpluginname(self, plugin, name):
if name is None:
if hasattr(plugin, '__name__'):
name = plugin.__name__.split(".")[-1]
else:
name = id(plugin)
return name
def register(self, plugin, name=None, prepend=False): def register(self, plugin, name=None, prepend=False):
assert not self.isregistered(plugin), plugin assert not self.isregistered(plugin), plugin
assert not self.isregistered(plugin), plugin name = name or getattr(plugin, '__name__', str(id(plugin)))
name = self._getpluginname(plugin, name)
if name in self._name2plugin: if name in self._name2plugin:
return False return False
#self.trace("registering", name, plugin)
self._name2plugin[name] = plugin self._name2plugin[name] = plugin
self.call_plugin(plugin, "pytest_addhooks", {'pluginmanager': self}) self.call_plugin(plugin, "pytest_addhooks", {'pluginmanager': self})
self.hook.pytest_plugin_registered(manager=self, plugin=plugin) self.hook.pytest_plugin_registered(manager=self, plugin=plugin)
@ -112,7 +102,7 @@ class PluginManager(object):
del self._name2plugin[name] del self._name2plugin[name]
def isregistered(self, plugin, name=None): def isregistered(self, plugin, name=None):
if self._getpluginname(plugin, name) in self._name2plugin: if self.getplugin(name) is not None:
return True return True
for val in self._name2plugin.values(): for val in self._name2plugin.values():
if plugin == val: if plugin == val:
@ -136,11 +126,12 @@ class PluginManager(object):
return False return False
def getplugin(self, name): def getplugin(self, name):
if name is None:
return None
try: try:
return self._name2plugin[name] return self._name2plugin[name]
except KeyError: except KeyError:
impname = canonical_importname(name) return self._name2plugin.get("_pytest." + name, None)
return self._name2plugin[impname]
# API for bootstrapping # API for bootstrapping
# #
@ -160,19 +151,28 @@ class PluginManager(object):
except ImportError: except ImportError:
return # XXX issue a warning return # XXX issue a warning
for ep in iter_entry_points('pytest11'): for ep in iter_entry_points('pytest11'):
name = canonical_importname(ep.name) if ep.name in self._name2plugin:
if name in self._name2plugin:
continue continue
try: try:
plugin = ep.load() plugin = ep.load()
except DistributionNotFound: except DistributionNotFound:
continue continue
name = ep.name
if name.startswith("pytest_"):
name = name[7:]
self.register(plugin, name=name) self.register(plugin, name=name)
def consider_preparse(self, args): def consider_preparse(self, args):
for opt1,opt2 in zip(args, args[1:]): for opt1,opt2 in zip(args, args[1:]):
if opt1 == "-p": if opt1 == "-p":
self.import_plugin(opt2) if opt2.startswith("no:"):
name = opt2[3:]
if self.getplugin(name) is not None:
self.unregister(None, name=name)
self._name2plugin[name] = -1
else:
if self.getplugin(opt2) is None:
self.import_plugin(opt2)
def consider_conftest(self, conftestmodule): def consider_conftest(self, conftestmodule):
if self.register(conftestmodule, name=conftestmodule.__file__): if self.register(conftestmodule, name=conftestmodule.__file__):
@ -186,15 +186,19 @@ class PluginManager(object):
for spec in attr: for spec in attr:
self.import_plugin(spec) self.import_plugin(spec)
def import_plugin(self, spec): def import_plugin(self, modname):
assert isinstance(spec, str) assert isinstance(modname, str)
modname = canonical_importname(spec) if self.getplugin(modname) is not None:
if modname in self._name2plugin:
return return
try: try:
#self.trace("importing", modname)
mod = importplugin(modname) mod = importplugin(modname)
except KeyboardInterrupt: except KeyboardInterrupt:
raise raise
except ImportError:
if modname.startswith("pytest_"):
return self.import_plugin(modname[7:])
raise
except: except:
e = py.std.sys.exc_info()[1] e = py.std.sys.exc_info()[1]
if not hasattr(py.test, 'skip'): if not hasattr(py.test, 'skip'):
@ -290,34 +294,18 @@ class PluginManager(object):
return MultiCall(methods=self.listattr(methname, plugins=[plugin]), return MultiCall(methods=self.listattr(methname, plugins=[plugin]),
kwargs=kwargs, firstresult=True).execute() kwargs=kwargs, firstresult=True).execute()
def canonical_importname(name):
if '.' in name:
return name
name = name.lower()
if not name.startswith(IMPORTPREFIX):
name = IMPORTPREFIX + name
return name
def importplugin(importspec): def importplugin(importspec):
#print "importing", importspec name = importspec
try: try:
return __import__(importspec, None, None, '__doc__') mod = "_pytest." + name
return __import__(mod, None, None, '__doc__')
except ImportError: except ImportError:
e = py.std.sys.exc_info()[1] #e = py.std.sys.exc_info()[1]
if str(e).find(importspec) == -1: #if str(e).find(name) == -1:
raise # raise
name = importspec pass #
try: return __import__(importspec, None, None, '__doc__')
if name.startswith("pytest_"):
name = importspec[7:]
return __import__("_pytest.%s" %(name), None, None, '__doc__')
except ImportError:
e = py.std.sys.exc_info()[1]
if str(e).find(name) == -1:
raise
# show the original exception, not the failing internal one
return __import__(importspec, None, None, '__doc__')
class MultiCall: class MultiCall:
""" execute a call into multiple python functions/methods. """ """ execute a call into multiple python functions/methods. """

View File

@ -80,7 +80,11 @@ def pytest_report_header(config):
plugins = [] plugins = []
items = config.pluginmanager._name2plugin.items() items = config.pluginmanager._name2plugin.items()
for name, plugin in items: for name, plugin in items:
lines.append(" %-20s: %s" %(name, repr(plugin))) if hasattr(plugin, '__file__'):
r = plugin.__file__
else:
r = repr(plugin)
lines.append(" %-20s: %s" %(name, r))
return lines return lines

View File

@ -40,7 +40,7 @@ def pytest_addoption(parser):
help="only load conftest.py's relative to specified dir.") help="only load conftest.py's relative to specified dir.")
group = parser.getgroup("debugconfig", group = parser.getgroup("debugconfig",
"test process debugging and configuration") "test session debugging and configuration")
group.addoption('--basetemp', dest="basetemp", default=None, metavar="dir", group.addoption('--basetemp', dest="basetemp", default=None, metavar="dir",
help="base temporary directory for this test run.") help="base temporary directory for this test run.")
@ -336,7 +336,7 @@ class Session(FSCollector):
def __init__(self, config): def __init__(self, config):
super(Session, self).__init__(py.path.local(), parent=None, super(Session, self).__init__(py.path.local(), parent=None,
config=config, session=self) config=config, session=self)
self.config.pluginmanager.register(self, name="session", prepend=True) assert self.config.pluginmanager.register(self, name="session", prepend=True)
self._testsfailed = 0 self._testsfailed = 0
self.shouldstop = False self.shouldstop = False
self.trace = config.trace.root.get("collection") self.trace = config.trace.root.get("collection")

View File

@ -6,7 +6,7 @@ import re
import inspect import inspect
import time import time
from fnmatch import fnmatch from fnmatch import fnmatch
from _pytest.session import Session from _pytest.main import Session
from py.builtin import print_ from py.builtin import print_
from _pytest.core import HookRelay from _pytest.core import HookRelay

View File

@ -730,7 +730,7 @@ class FuncargRequest:
raise self.LookupError(msg) raise self.LookupError(msg)
def showfuncargs(config): def showfuncargs(config):
from _pytest.session import Session from _pytest.main import Session
session = Session(config) session = Session(config)
session.perform_collect() session.perform_collect()
if session.items: if session.items:

View File

@ -1,12 +1,12 @@
""" (disabled by default) create result information in a plain text file. """ """ (disabled by default) create result information in a plain text file. """
import py import py
from py.builtin import print_
def pytest_addoption(parser): def pytest_addoption(parser):
group = parser.getgroup("resultlog", "resultlog plugin options") group = parser.getgroup("terminal reporting", "resultlog plugin options")
group.addoption('--resultlog', action="store", dest="resultlog", metavar="path", default=None, group.addoption('--resultlog', action="store", dest="resultlog",
help="path for machine-readable result log.") metavar="path", default=None,
help="path for machine-readable result log.")
def pytest_configure(config): def pytest_configure(config):
resultlog = config.option.resultlog resultlog = config.option.resultlog
@ -52,9 +52,9 @@ class ResultLog(object):
self.logfile = logfile # preferably line buffered self.logfile = logfile # preferably line buffered
def write_log_entry(self, testpath, lettercode, longrepr): def write_log_entry(self, testpath, lettercode, longrepr):
print_("%s %s" % (lettercode, testpath), file=self.logfile) py.builtin.print_("%s %s" % (lettercode, testpath), file=self.logfile)
for line in longrepr.splitlines(): for line in longrepr.splitlines():
print_(" %s" % line, file=self.logfile) py.builtin.print_(" %s" % line, file=self.logfile)
def log_outcome(self, report, lettercode, longrepr): def log_outcome(self, report, lettercode, longrepr):
testpath = getattr(report, 'nodeid', None) testpath = getattr(report, 'nodeid', None)

View File

@ -10,7 +10,6 @@
.. _pytest: http://pypi.python.org/pypi/pytest .. _pytest: http://pypi.python.org/pypi/pytest
.. _mercurial: http://mercurial.selenic.com/wiki/ .. _mercurial: http://mercurial.selenic.com/wiki/
.. _`setuptools`: http://pypi.python.org/pypi/setuptools .. _`setuptools`: http://pypi.python.org/pypi/setuptools
.. _`easy_install`: .. _`easy_install`:
.. _`distribute docs`: .. _`distribute docs`:
.. _`distribute`: http://pypi.python.org/pypi/distribute .. _`distribute`: http://pypi.python.org/pypi/distribute

View File

@ -1,4 +1,4 @@
Writing, managing and understanding plugins Working with plugins and conftest files
============================================= =============================================
.. _`local plugin`: .. _`local plugin`:
@ -11,6 +11,7 @@ py.test implements all aspects of configuration, collection, running and reporti
.. _`pytest/plugin`: http://bitbucket.org/hpk42/pytest/src/tip/pytest/plugin/ .. _`pytest/plugin`: http://bitbucket.org/hpk42/pytest/src/tip/pytest/plugin/
.. _`conftest.py plugins`: .. _`conftest.py plugins`:
.. _`conftest.py`:
conftest.py: local per-directory plugins conftest.py: local per-directory plugins
-------------------------------------------------------------- --------------------------------------------------------------
@ -53,6 +54,7 @@ earlier than further away ones.
conftest.py file. conftest.py file.
.. _`external plugins`: .. _`external plugins`:
.. _`extplugins`:
Installing External Plugins / Searching Installing External Plugins / Searching
------------------------------------------------------ ------------------------------------------------------
@ -64,9 +66,26 @@ tool, for example::
pip uninstall pytest-NAME pip uninstall pytest-NAME
If a plugin is installed, py.test automatically finds and integrates it, If a plugin is installed, py.test automatically finds and integrates it,
there is no need to activate it. If you don't need a plugin anymore simply there is no need to activate it. Here is a list of known plugins:
de-install it. You can find a list of available plugins through a
`pytest- pypi.python.org search`_. * `pytest-capturelog <http://pypi.python.org/pypi/pytest-capturelog>`_:
to capture and assert about messages from the logging module
* `pytest-xdist <http://pypi.python.org/pypi/pytest-xdist>`_:
to distribute tests to CPUs and remote hosts, looponfailing mode,
see also :ref:`xdist`
* `pytest-cov <http://pypi.python.org/pypi/pytest-cov>`_:
coverage reporting, compatible with distributed testing
* `pytest-pep8 <http://pypi.python.org/pypi/pytest-pep8>`_:
a ``--pep8`` option to enable PEP8 compliancy checking.
* `oejskit <http://pypi.python.org/pypi/oejskit>`_:
a plugin to run javascript unittests in life browsers
(**version 0.8.9 not compatible with pytest-2.0**)
You may discover more plugins through a `pytest- pypi.python.org search`_.
.. _`available installable plugins`: .. _`available installable plugins`:
.. _`pytest- pypi.python.org search`: http://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search .. _`pytest- pypi.python.org search`: http://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search
@ -170,12 +189,42 @@ the plugin manager like this:
If you want to look at the names of existing plugins, use If you want to look at the names of existing plugins, use
the ``--traceconfig`` option. the ``--traceconfig`` option.
.. _`findpluginname`:
Finding out which plugins are active
----------------------------------------------------------------------------
If you want to find out which plugins are active in your
environment you can type::
py.test --traceconfig
and will get an extended test header which shows activated plugins
and their names. It will also print local plugins aka
:ref:`conftest.py <conftest>` files when they are loaded.
.. _`cmdunregister`:
deactivate / unregister a plugin by name
----------------------------------------------------------------------------
You can prevent plugins from loading or unregister them::
py.test -p no:NAME
This means that any subsequent try to activate/load the named
plugin will it already existing. See :ref:`findpluginname` for
how to obtain the name of a plugin.
.. _`builtin plugins`: .. _`builtin plugins`:
py.test default plugin reference py.test default plugin reference
==================================== ====================================
You can find the source code for the following plugins
in the `pytest repository <http://bitbucket.org/hpk42/pytest/>`_.
.. autosummary:: .. autosummary::
_pytest.assertion _pytest.assertion
@ -195,7 +244,7 @@ py.test default plugin reference
_pytest.recwarn _pytest.recwarn
_pytest.resultlog _pytest.resultlog
_pytest.runner _pytest.runner
_pytest.session _pytest.main
_pytest.skipping _pytest.skipping
_pytest.terminal _pytest.terminal
_pytest.tmpdir _pytest.tmpdir
@ -288,14 +337,14 @@ Reference of important objects involved in hooks
.. autoclass:: _pytest.config.Parser .. autoclass:: _pytest.config.Parser
:members: :members:
.. autoclass:: _pytest.session.Node(name, parent) .. autoclass:: _pytest.main.Node(name, parent)
:members: :members:
.. ..
.. autoclass:: _pytest.session.File(fspath, parent) .. autoclass:: _pytest.main.File(fspath, parent)
:members: :members:
.. autoclass:: _pytest.session.Item(name, parent) .. autoclass:: _pytest.main.Item(name, parent)
:members: :members:
.. autoclass:: _pytest.python.Module(name, parent) .. autoclass:: _pytest.python.Module(name, parent)
@ -313,4 +362,3 @@ Reference of important objects involved in hooks
.. autoclass:: _pytest.runner.TestReport .. autoclass:: _pytest.runner.TestReport
:members: :members:

View File

@ -27,7 +27,7 @@ class TestGeneralUsage:
def test_option(pytestconfig): def test_option(pytestconfig):
assert pytestconfig.option.xyz == "123" assert pytestconfig.option.xyz == "123"
""") """)
result = testdir.runpytest("-p", "xyz", "--xyz=123") result = testdir.runpytest("-p", "pytest_xyz", "--xyz=123")
assert result.ret == 0 assert result.ret == 0
result.stdout.fnmatch_lines([ result.stdout.fnmatch_lines([
'*1 passed*', '*1 passed*',

View File

@ -1,6 +1,6 @@
import pytest, py import pytest, py
from _pytest.session import Session from _pytest.main import Session
class TestCollector: class TestCollector:
def test_collect_versus_item(self): def test_collect_versus_item(self):

View File

@ -219,7 +219,7 @@ def test_options_on_small_file_do_not_blow_up(testdir):
['--traceconfig'], ['-v'], ['-v', '-v']): ['--traceconfig'], ['-v'], ['-v', '-v']):
runfiletest(opts + [path]) runfiletest(opts + [path])
def test_preparse_ordering(testdir, monkeypatch): def test_preparse_ordering_with_setuptools(testdir, monkeypatch):
pkg_resources = py.test.importorskip("pkg_resources") pkg_resources = py.test.importorskip("pkg_resources")
def my_iter(name): def my_iter(name):
assert name == "pytest11" assert name == "pytest11"
@ -239,3 +239,16 @@ def test_preparse_ordering(testdir, monkeypatch):
plugin = config.pluginmanager.getplugin("mytestplugin") plugin = config.pluginmanager.getplugin("mytestplugin")
assert plugin.x == 42 assert plugin.x == 42
def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch):
pkg_resources = py.test.importorskip("pkg_resources")
def my_iter(name):
assert name == "pytest11"
class EntryPoint:
name = "mytestplugin"
def load(self):
assert 0, "should not arrive here"
return iter([EntryPoint()])
monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter)
config = testdir.parseconfig("-p", "no:mytestplugin")
plugin = config.pluginmanager.getplugin("mytestplugin")
assert plugin == -1

View File

@ -1,5 +1,5 @@
import pytest, py, os import pytest, py, os
from _pytest.core import PluginManager, canonical_importname from _pytest.core import PluginManager
from _pytest.core import MultiCall, HookRelay, varnames from _pytest.core import MultiCall, HookRelay, varnames
@ -15,30 +15,47 @@ class TestBootstrapping:
pluginmanager.consider_preparse(["xyz", "-p", "hello123"]) pluginmanager.consider_preparse(["xyz", "-p", "hello123"])
""") """)
def test_plugin_prevent_register(self):
pluginmanager = PluginManager()
pluginmanager.consider_preparse(["xyz", "-p", "no:abc"])
l1 = pluginmanager.getplugins()
pluginmanager.register(42, name="abc")
l2 = pluginmanager.getplugins()
assert len(l2) == len(l1)
def test_plugin_prevent_register_unregistered_alredy_registered(self):
pluginmanager = PluginManager()
pluginmanager.register(42, name="abc")
l1 = pluginmanager.getplugins()
assert 42 in l1
pluginmanager.consider_preparse(["xyz", "-p", "no:abc"])
l2 = pluginmanager.getplugins()
assert 42 not in l2
def test_plugin_skip(self, testdir, monkeypatch): def test_plugin_skip(self, testdir, monkeypatch):
p = testdir.makepyfile(pytest_skipping1=""" p = testdir.makepyfile(skipping1="""
import pytest import pytest
pytest.skip("hello") pytest.skip("hello")
""") """)
p.copy(p.dirpath("pytest_skipping2.py")) p.copy(p.dirpath("skipping2.py"))
monkeypatch.setenv("PYTEST_PLUGINS", "skipping2") monkeypatch.setenv("PYTEST_PLUGINS", "skipping2")
result = testdir.runpytest("-p", "skipping1", "--traceconfig") result = testdir.runpytest("-p", "skipping1", "--traceconfig")
assert result.ret == 0 assert result.ret == 0
result.stdout.fnmatch_lines([ result.stdout.fnmatch_lines([
"*hint*skipping2*hello*",
"*hint*skipping1*hello*", "*hint*skipping1*hello*",
"*hint*skipping2*hello*",
]) ])
def test_consider_env_plugin_instantiation(self, testdir, monkeypatch): def test_consider_env_plugin_instantiation(self, testdir, monkeypatch):
pluginmanager = PluginManager() pluginmanager = PluginManager()
testdir.syspathinsert() testdir.syspathinsert()
testdir.makepyfile(pytest_xy123="#") testdir.makepyfile(xy123="#")
monkeypatch.setitem(os.environ, 'PYTEST_PLUGINS', 'xy123') monkeypatch.setitem(os.environ, 'PYTEST_PLUGINS', 'xy123')
l1 = len(pluginmanager.getplugins()) l1 = len(pluginmanager.getplugins())
pluginmanager.consider_env() pluginmanager.consider_env()
l2 = len(pluginmanager.getplugins()) l2 = len(pluginmanager.getplugins())
assert l2 == l1 + 1 assert l2 == l1 + 1
assert pluginmanager.getplugin('pytest_xy123') assert pluginmanager.getplugin('xy123')
pluginmanager.consider_env() pluginmanager.consider_env()
l3 = len(pluginmanager.getplugins()) l3 = len(pluginmanager.getplugins())
assert l2 == l3 assert l2 == l3
@ -48,7 +65,7 @@ class TestBootstrapping:
def my_iter(name): def my_iter(name):
assert name == "pytest11" assert name == "pytest11"
class EntryPoint: class EntryPoint:
name = "mytestplugin" name = "pytest_mytestplugin"
def load(self): def load(self):
class PseudoPlugin: class PseudoPlugin:
x = 42 x = 42
@ -60,8 +77,6 @@ class TestBootstrapping:
pluginmanager.consider_setuptools_entrypoints() pluginmanager.consider_setuptools_entrypoints()
plugin = pluginmanager.getplugin("mytestplugin") plugin = pluginmanager.getplugin("mytestplugin")
assert plugin.x == 42 assert plugin.x == 42
plugin2 = pluginmanager.getplugin("pytest_mytestplugin")
assert plugin2 == plugin
def test_consider_setuptools_not_installed(self, monkeypatch): def test_consider_setuptools_not_installed(self, monkeypatch):
monkeypatch.setitem(py.std.sys.modules, 'pkg_resources', monkeypatch.setitem(py.std.sys.modules, 'pkg_resources',
@ -75,7 +90,7 @@ class TestBootstrapping:
p = testdir.makepyfile(""" p = testdir.makepyfile("""
import pytest import pytest
def test_hello(pytestconfig): def test_hello(pytestconfig):
plugin = pytestconfig.pluginmanager.getplugin('x500') plugin = pytestconfig.pluginmanager.getplugin('pytest_x500')
assert plugin is not None assert plugin is not None
""") """)
monkeypatch.setenv('PYTEST_PLUGINS', 'pytest_x500', prepend=",") monkeypatch.setenv('PYTEST_PLUGINS', 'pytest_x500', prepend=",")
@ -91,14 +106,14 @@ class TestBootstrapping:
reset = testdir.syspathinsert() reset = testdir.syspathinsert()
pluginname = "pytest_hello" pluginname = "pytest_hello"
testdir.makepyfile(**{pluginname: ""}) testdir.makepyfile(**{pluginname: ""})
pluginmanager.import_plugin("hello") pluginmanager.import_plugin("pytest_hello")
len1 = len(pluginmanager.getplugins()) len1 = len(pluginmanager.getplugins())
pluginmanager.import_plugin("pytest_hello") pluginmanager.import_plugin("pytest_hello")
len2 = len(pluginmanager.getplugins()) len2 = len(pluginmanager.getplugins())
assert len1 == len2 assert len1 == len2
plugin1 = pluginmanager.getplugin("pytest_hello") plugin1 = pluginmanager.getplugin("pytest_hello")
assert plugin1.__name__.endswith('pytest_hello') assert plugin1.__name__.endswith('pytest_hello')
plugin2 = pluginmanager.getplugin("hello") plugin2 = pluginmanager.getplugin("pytest_hello")
assert plugin2 is plugin1 assert plugin2 is plugin1
def test_import_plugin_dotted_name(self, testdir): def test_import_plugin_dotted_name(self, testdir):
@ -116,13 +131,13 @@ class TestBootstrapping:
def test_consider_module(self, testdir): def test_consider_module(self, testdir):
pluginmanager = PluginManager() pluginmanager = PluginManager()
testdir.syspathinsert() testdir.syspathinsert()
testdir.makepyfile(pytest_plug1="#") testdir.makepyfile(pytest_p1="#")
testdir.makepyfile(pytest_plug2="#") testdir.makepyfile(pytest_p2="#")
mod = py.std.types.ModuleType("temp") mod = py.std.types.ModuleType("temp")
mod.pytest_plugins = ["pytest_plug1", "pytest_plug2"] mod.pytest_plugins = ["pytest_p1", "pytest_p2"]
pluginmanager.consider_module(mod) pluginmanager.consider_module(mod)
assert pluginmanager.getplugin("plug1").__name__ == "pytest_plug1" assert pluginmanager.getplugin("pytest_p1").__name__ == "pytest_p1"
assert pluginmanager.getplugin("plug2").__name__ == "pytest_plug2" assert pluginmanager.getplugin("pytest_p2").__name__ == "pytest_p2"
def test_consider_module_import_module(self, testdir): def test_consider_module_import_module(self, testdir):
mod = py.std.types.ModuleType("x") mod = py.std.types.ModuleType("x")
@ -198,8 +213,7 @@ class TestBootstrapping:
mod = py.std.types.ModuleType("pytest_xyz") mod = py.std.types.ModuleType("pytest_xyz")
monkeypatch.setitem(py.std.sys.modules, 'pytest_xyz', mod) monkeypatch.setitem(py.std.sys.modules, 'pytest_xyz', mod)
pp = PluginManager() pp = PluginManager()
pp.import_plugin('xyz') pp.import_plugin('pytest_xyz')
assert pp.getplugin('xyz') == mod
assert pp.getplugin('pytest_xyz') == mod assert pp.getplugin('pytest_xyz') == mod
assert pp.isregistered(mod) assert pp.isregistered(mod)
@ -217,9 +231,6 @@ class TestBootstrapping:
pass pass
excinfo = pytest.raises(Exception, "pp.register(hello())") excinfo = pytest.raises(Exception, "pp.register(hello())")
def test_canonical_importname(self):
for name in 'xyz', 'pytest_xyz', 'pytest_Xyz', 'Xyz':
impname = canonical_importname(name)
def test_notify_exception(self, capfd): def test_notify_exception(self, capfd):
pp = PluginManager() pp = PluginManager()
@ -400,7 +411,7 @@ class TestPytestPluginInteractions:
assert len(l) == 0 assert len(l) == 0
config.pluginmanager.do_configure(config=config) config.pluginmanager.do_configure(config=config)
assert len(l) == 1 assert len(l) == 1
config.pluginmanager.register(A()) # this should lead to a configured() plugin config.pluginmanager.register(A()) # leads to a configured() plugin
assert len(l) == 2 assert len(l) == 2
assert l[0] != l[1] assert l[0] != l[1]

View File

@ -2,10 +2,10 @@ import py, pytest
import os import os
from _pytest.resultlog import generic_path, ResultLog, \ from _pytest.resultlog import generic_path, ResultLog, \
pytest_configure, pytest_unconfigure pytest_configure, pytest_unconfigure
from _pytest.session import Node, Item, FSCollector from _pytest.main import Node, Item, FSCollector
def test_generic_path(testdir): def test_generic_path(testdir):
from _pytest.session import Session from _pytest.main import Session
config = testdir.parseconfig() config = testdir.parseconfig()
session = Session(config) session = Session(config)
p1 = Node('a', config=config, session=session) p1 = Node('a', config=config, session=session)

View File

@ -212,8 +212,8 @@ def test_plugin_specify(testdir):
#) #)
def test_plugin_already_exists(testdir): def test_plugin_already_exists(testdir):
config = testdir.parseconfig("-p", "session") config = testdir.parseconfig("-p", "terminal")
assert config.option.plugins == ['session'] assert config.option.plugins == ['terminal']
config.pluginmanager.do_configure(config) config.pluginmanager.do_configure(config)
def test_exclude(testdir): def test_exclude(testdir):

View File

@ -68,7 +68,7 @@ commands=
[pytest] [pytest]
minversion=2.0 minversion=2.0
plugins=pytester plugins=pytester
addopts= -rxf --pyargs --doctest-modules --ignore=.tox #addopts= -rxf --pyargs --doctest-modules --ignore=.tox
rsyncdirs=tox.ini pytest.py _pytest testing rsyncdirs=tox.ini pytest.py _pytest testing
python_files=test_*.py *_test.py python_files=test_*.py *_test.py
python_classes=Test Acceptance python_classes=Test Acceptance