[svn r62211] merge 60797:HEAD of pytestplugin branch:
this merge contains: * a new plugin architecture * a pluginized pytest core * many pytest related refactorings * refactorings/streamlining of pytest's own tests --HG-- branch : trunk
This commit is contained in:
@@ -71,3 +71,11 @@ def strip_html_header(string, encoding='utf8'):
|
||||
break
|
||||
uni = match.group(1)
|
||||
return uni
|
||||
|
||||
class Project: # used for confrest.py files
|
||||
def __init__(self, sourcepath):
|
||||
self.sourcepath = sourcepath
|
||||
def process(self, path):
|
||||
return process(path)
|
||||
def get_htmloutputpath(self, path):
|
||||
return path.new(ext='html')
|
||||
|
||||
@@ -52,7 +52,7 @@ class TestBuildcostAccess(BasicCacheAPITest):
|
||||
|
||||
|
||||
class TestAging(BasicCacheAPITest):
|
||||
maxsecs = 0.02
|
||||
maxsecs = 0.10
|
||||
cache = AgingCache(maxentries=128, maxseconds=maxsecs)
|
||||
|
||||
def test_cache_eviction(self):
|
||||
|
||||
233
py/misc/testing/test_com.py
Normal file
233
py/misc/testing/test_com.py
Normal file
@@ -0,0 +1,233 @@
|
||||
|
||||
import py
|
||||
import os
|
||||
from py._com import PyPlugins, MultiCall
|
||||
|
||||
pytest_plugins = "xfail"
|
||||
|
||||
class TestMultiCall:
|
||||
def test_call_passing(self):
|
||||
class P1:
|
||||
def m(self, __call__, x):
|
||||
assert __call__.currentmethod == self.m
|
||||
assert len(__call__.results) == 1
|
||||
assert not __call__.methods
|
||||
return 17
|
||||
|
||||
class P2:
|
||||
def m(self, __call__, x):
|
||||
assert __call__.currentmethod == self.m
|
||||
assert __call__.args
|
||||
assert __call__.results == []
|
||||
assert __call__.methods
|
||||
return 23
|
||||
|
||||
p1 = P1()
|
||||
p2 = P2()
|
||||
multicall = MultiCall([p1.m, p2.m], 23)
|
||||
reslist = multicall.execute()
|
||||
assert len(reslist) == 2
|
||||
# ensure reversed order
|
||||
assert reslist == [23, 17]
|
||||
|
||||
def test_optionalcallarg(self):
|
||||
class P1:
|
||||
def m(self, x):
|
||||
return x
|
||||
call = MultiCall([P1().m], 23)
|
||||
assert call.execute() == [23]
|
||||
assert call.execute(firstresult=True) == 23
|
||||
|
||||
def test_call_subexecute(self):
|
||||
def m(__call__):
|
||||
subresult = __call__.execute(firstresult=True)
|
||||
return subresult + 1
|
||||
|
||||
def n():
|
||||
return 1
|
||||
|
||||
call = MultiCall([n, m])
|
||||
res = call.execute(firstresult=True)
|
||||
assert res == 2
|
||||
|
||||
class TestPyPlugins:
|
||||
def test_MultiCall(self):
|
||||
plugins = PyPlugins()
|
||||
assert hasattr(plugins, "MultiCall")
|
||||
|
||||
def test_register(self):
|
||||
plugins = PyPlugins()
|
||||
class MyPlugin:
|
||||
pass
|
||||
my = MyPlugin()
|
||||
plugins.register(my)
|
||||
assert plugins.getplugins() == [my]
|
||||
my2 = MyPlugin()
|
||||
plugins.register(my2)
|
||||
assert plugins.getplugins() == [my, my2]
|
||||
|
||||
assert plugins.isregistered(my)
|
||||
assert plugins.isregistered(my2)
|
||||
plugins.unregister(my)
|
||||
assert not plugins.isregistered(my)
|
||||
assert plugins.getplugins() == [my2]
|
||||
|
||||
#@py.test.keywords(xfail=True)
|
||||
def test_onregister(self):
|
||||
py.test.skip("implement exitfirst plugin and "
|
||||
"modify xfail plugin to override exitfirst behaviour?")
|
||||
plugins = PyPlugins()
|
||||
l = []
|
||||
class MyApi:
|
||||
def pyevent_plugin_registered(self, plugin):
|
||||
l.append(plugin)
|
||||
def pyevent_plugin_unregistered(self, plugin):
|
||||
l.remove(plugin)
|
||||
myapi = MyApi()
|
||||
plugins.register(myapi)
|
||||
assert len(l) == 1
|
||||
assert l[0] is myapi
|
||||
plugins.unregister(myapi)
|
||||
assert not l
|
||||
|
||||
def test_call_methods(self):
|
||||
plugins = PyPlugins()
|
||||
class api1:
|
||||
def m(self, __call__, x):
|
||||
return x
|
||||
class api2:
|
||||
def m(self, __call__, x, y=33):
|
||||
return y
|
||||
plugins.register(api1())
|
||||
plugins.register(api2())
|
||||
res = plugins.call_firstresult("m", x=5)
|
||||
assert plugins.call_firstresult("notexist") is None
|
||||
|
||||
assert res == 33
|
||||
reslist = plugins.call_each("m", x=5)
|
||||
assert len(reslist) == 2
|
||||
assert 5 in reslist
|
||||
assert 33 in reslist
|
||||
assert plugins.call_each("notexist") == []
|
||||
|
||||
assert plugins.call_plugin(api1(), 'm', x=12) == 12
|
||||
assert plugins.call_plugin(api2(), 't') is None
|
||||
|
||||
def test_call_none_is_no_result(self):
|
||||
plugins = PyPlugins()
|
||||
class api1:
|
||||
def m(self):
|
||||
return None
|
||||
class api2:
|
||||
def m(self, __call__):
|
||||
return 41
|
||||
plugins.register(api1())
|
||||
plugins.register(api1())
|
||||
plugins.register(api2())
|
||||
assert plugins.call_firstresult('m') == 41
|
||||
assert plugins.call_each('m') == [41]
|
||||
|
||||
def test_call_noneasresult(self):
|
||||
plugins = PyPlugins()
|
||||
class api1:
|
||||
def m(self, __call__):
|
||||
return __call__.NONEASRESULT
|
||||
plugins.register(api1())
|
||||
plugins.register(api1())
|
||||
assert plugins.call_firstresult('m') is None
|
||||
assert plugins.call_each('m') == [None, None]
|
||||
|
||||
def test_listattr(self):
|
||||
plugins = PyPlugins()
|
||||
class api1:
|
||||
x = 42
|
||||
class api2:
|
||||
x = 41
|
||||
plugins.register(api1())
|
||||
plugins.register(api2())
|
||||
l = list(plugins.listattr('x'))
|
||||
l.sort()
|
||||
assert l == [41, 42]
|
||||
|
||||
def test_notify_anonymous_ordered(self):
|
||||
plugins = PyPlugins()
|
||||
l = []
|
||||
class api1:
|
||||
def pyevent_hello(self):
|
||||
l.append("hellospecific")
|
||||
class api2:
|
||||
def pyevent(self, name, *args):
|
||||
if name == "hello":
|
||||
l.append(name + "anonymous")
|
||||
plugins.register(api1())
|
||||
plugins.register(api2())
|
||||
plugins.notify('hello')
|
||||
assert l == ["hellospecific", "helloanonymous"]
|
||||
|
||||
def test_consider_env(self, monkeypatch):
|
||||
# XXX write a helper for preserving os.environ
|
||||
plugins = PyPlugins()
|
||||
monkeypatch.setitem(os.environ, 'PYLIB', "unknownconsider_env")
|
||||
py.test.raises(ImportError, "plugins.consider_env()")
|
||||
|
||||
def test_consider_module(self):
|
||||
plugins = PyPlugins()
|
||||
mod = py.std.new.module("temp")
|
||||
mod.pylib = ["xxx nomod"]
|
||||
excinfo = py.test.raises(ImportError, "plugins.consider_module(mod)")
|
||||
mod.pylib = "os"
|
||||
class Events(list):
|
||||
def pyevent_importingmodule(self, mod):
|
||||
self.append(mod)
|
||||
l = Events()
|
||||
plugins.register(l)
|
||||
plugins.consider_module(mod)
|
||||
assert len(l) == 1
|
||||
assert l[0] == (mod.pylib)
|
||||
|
||||
def test_api_and_defaults():
|
||||
assert isinstance(py._com.pyplugins, PyPlugins)
|
||||
|
||||
def test_subprocess_env():
|
||||
# XXX write a helper for preserving os.environ
|
||||
plugins = PyPlugins()
|
||||
KEY = "PYLIB"
|
||||
old = os.environ.get(KEY, None)
|
||||
olddir = py.path.local(py.__file__).dirpath().dirpath().chdir()
|
||||
try:
|
||||
os.environ[KEY] = "unknownconsider_env"
|
||||
excinfo = py.test.raises(py.process.cmdexec.Error, """
|
||||
py.process.cmdexec("python -c 'import py'")
|
||||
""")
|
||||
assert str(excinfo.value).find("ImportError") != -1
|
||||
assert str(excinfo.value).find("unknownconsider") != -1
|
||||
finally:
|
||||
olddir.chdir()
|
||||
if old is None:
|
||||
del os.environ[KEY]
|
||||
else:
|
||||
os.environ[KEY] = old
|
||||
|
||||
class TestPyPluginsEvents:
|
||||
def test_pyevent_named_dispatch(self):
|
||||
plugins = PyPlugins()
|
||||
l = []
|
||||
class A:
|
||||
def pyevent_name(self, x):
|
||||
l.append(x)
|
||||
plugins.register(A())
|
||||
plugins.notify("name", 13)
|
||||
assert l == [13]
|
||||
|
||||
def test_pyevent_anonymous_dispatch(self):
|
||||
plugins = PyPlugins()
|
||||
l = []
|
||||
class A:
|
||||
def pyevent(self, name, *args, **kwargs):
|
||||
if name == "name":
|
||||
l.extend([args, kwargs])
|
||||
|
||||
plugins.register(A())
|
||||
plugins.notify("name", 13, x=15)
|
||||
assert l == [(13, ), {'x':15}]
|
||||
|
||||
@@ -12,20 +12,20 @@ def checksubpackage(name):
|
||||
assert getattr(obj, '__map__') == {}
|
||||
|
||||
def test_dir():
|
||||
from py.__.initpkg import Module
|
||||
from py.__.initpkg import ApiModule
|
||||
for name in dir(py):
|
||||
if name == 'magic': # greenlets don't work everywhere, we don't care here
|
||||
continue
|
||||
if not name.startswith('_'):
|
||||
yield checksubpackage, name
|
||||
|
||||
from py.initpkg import Module
|
||||
from py.initpkg import ApiModule
|
||||
glob = []
|
||||
class MyModule(Module):
|
||||
class MyModule(ApiModule):
|
||||
def __init__(self, *args):
|
||||
glob.append(self.__dict__)
|
||||
assert isinstance(glob[-1], (dict, type(None)))
|
||||
Module.__init__(self, *args)
|
||||
ApiModule.__init__(self, *args)
|
||||
|
||||
def test_early__dict__access():
|
||||
mymod = MyModule("whatever", "myname")
|
||||
@@ -68,7 +68,10 @@ def test_importall():
|
||||
base.join('execnet', 'script'),
|
||||
base.join('compat', 'testing'),
|
||||
)
|
||||
for p in base.visit('*.py', lambda x: x.check(dotfile=0)):
|
||||
def recurse(p):
|
||||
return p.check(dotfile=0) and p.basename != "attic"
|
||||
|
||||
for p in base.visit('*.py', recurse):
|
||||
if p.basename == '__init__.py':
|
||||
continue
|
||||
relpath = p.new(ext='').relto(base)
|
||||
@@ -255,3 +258,8 @@ class TestRealModule:
|
||||
# help(std.path)
|
||||
# #assert False
|
||||
|
||||
|
||||
def test_autoimport():
|
||||
from py.initpkg import autoimport
|
||||
py.std.os.environ['AUTOTEST_AUTOIMPORT'] = "nonexistmodule"
|
||||
py.test.raises(ImportError, "autoimport('autotest')")
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import py
|
||||
from py.__.misc.warn import WarningBus
|
||||
from py.__.misc.warn import WarningPlugin
|
||||
mypath = py.magic.autopath()
|
||||
|
||||
class TestWarningBus:
|
||||
class TestWarningPlugin:
|
||||
def setup_method(self, method):
|
||||
self.wb = WarningBus()
|
||||
self.bus = py._com.PyPlugins()
|
||||
self.wb = WarningPlugin(self.bus)
|
||||
self.bus.register(self)
|
||||
self.warnings = []
|
||||
self.wb.subscribe(self.warnings.append)
|
||||
|
||||
def test_basic(self):
|
||||
def pyevent_WARNING(self, warning):
|
||||
self.warnings.append(warning)
|
||||
|
||||
def test_event_generation(self):
|
||||
self.wb.warn("hello")
|
||||
assert len(self.warnings) == 1
|
||||
self.wb.unsubscribe(self.warnings.append)
|
||||
self.wb.warn("this")
|
||||
assert len(self.warnings) == 1
|
||||
w = self.warnings[0]
|
||||
|
||||
def test_location(self):
|
||||
self.wb.warn("again")
|
||||
@@ -27,19 +27,16 @@ class TestWarningBus:
|
||||
assert str(warning) == warning.msg
|
||||
|
||||
def test_stacklevel(self):
|
||||
l = []
|
||||
self.wb.subscribe(l.append)
|
||||
def f():
|
||||
self.wb.warn("x", stacklevel=2)
|
||||
# 5
|
||||
# 6
|
||||
# 3
|
||||
# 4
|
||||
f()
|
||||
lno = self.test_stacklevel.im_func.func_code.co_firstlineno + 7
|
||||
warning = l[0]
|
||||
lno = self.test_stacklevel.im_func.func_code.co_firstlineno + 5
|
||||
warning = self.warnings[0]
|
||||
assert warning.lineno == lno
|
||||
|
||||
def test_forwarding_to_warnings_module(self):
|
||||
self.wb._setforwarding()
|
||||
py.test.deprecated_call(self.wb.warn, "x")
|
||||
|
||||
def test_apiwarn(self):
|
||||
@@ -47,7 +44,6 @@ class TestWarningBus:
|
||||
warning = self.warnings[0]
|
||||
assert warning.msg == "xxx (since version 3.0)"
|
||||
|
||||
def test_APIWARN():
|
||||
def test_default():
|
||||
from py.__.misc.warn import APIWARN
|
||||
wb = APIWARN.im_self
|
||||
assert wb._forward in wb._eventbus._subscribers
|
||||
assert py._com.pyplugins.isregistered(APIWARN.im_self)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import py, sys
|
||||
from py.__.test.event import EventBus
|
||||
|
||||
class Warning(py.std.exceptions.DeprecationWarning):
|
||||
def __init__(self, msg, path, lineno):
|
||||
@@ -11,19 +10,16 @@ class Warning(py.std.exceptions.DeprecationWarning):
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
class WarningBus(object):
|
||||
def __init__(self):
|
||||
self._eventbus = EventBus()
|
||||
# XXX probably only apiwarn() + py._com.pyplugins forwarding
|
||||
# warn_explicit is actually needed
|
||||
|
||||
def subscribe(self, callable):
|
||||
self._eventbus.subscribe(callable)
|
||||
|
||||
def unsubscribe(self, callable):
|
||||
self._eventbus.unsubscribe(callable)
|
||||
|
||||
def _setforwarding(self):
|
||||
self._eventbus.subscribe(self._forward)
|
||||
def _forward(self, warning):
|
||||
class WarningPlugin(object):
|
||||
def __init__(self, bus):
|
||||
self.bus = bus
|
||||
bus.register(self)
|
||||
|
||||
def pyevent_WARNING(self, warning):
|
||||
# forward to python warning system
|
||||
py.std.warnings.warn_explicit(warning, category=Warning,
|
||||
filename=str(warning.path),
|
||||
lineno=warning.lineno,
|
||||
@@ -66,9 +62,8 @@ class WarningBus(object):
|
||||
filename = module
|
||||
path = py.path.local(filename)
|
||||
warning = Warning(msg, path, lineno)
|
||||
self._eventbus.notify(warning)
|
||||
self.bus.notify("WARNING", warning)
|
||||
|
||||
# singleton api warner for py lib
|
||||
apiwarner = WarningBus()
|
||||
apiwarner._setforwarding()
|
||||
apiwarner = WarningPlugin(py._com.pyplugins)
|
||||
APIWARN = apiwarner.apiwarn
|
||||
|
||||
Reference in New Issue
Block a user