[svn r57744] Merging collection-API refactoring branch:
* collectors now have a collect() method * items have a runtest() method * deprecated old run/join of collectors and run/execute methods of items --HG-- branch : trunk
This commit is contained in:
parent
ee94d1d2bd
commit
494ea31042
|
@ -120,7 +120,7 @@ class Node(object):
|
||||||
#self.__init__(name=name, parent=parent)
|
#self.__init__(name=name, parent=parent)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self._config.option.debug:
|
if getattr(self._config.option, 'debug', False):
|
||||||
return "<%s %r %0x>" %(self.__class__.__name__,
|
return "<%s %r %0x>" %(self.__class__.__name__,
|
||||||
getattr(self, 'name', None), id(self))
|
getattr(self, 'name', None), id(self))
|
||||||
else:
|
else:
|
||||||
|
@ -153,6 +153,24 @@ class Node(object):
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def _memoizedcall(self, attrname, function):
|
||||||
|
exattrname = "_ex_" + attrname
|
||||||
|
failure = getattr(self, exattrname, None)
|
||||||
|
if failure is not None:
|
||||||
|
raise failure[0], failure[1], failure[2]
|
||||||
|
if hasattr(self, attrname):
|
||||||
|
return getattr(self, attrname)
|
||||||
|
try:
|
||||||
|
res = function()
|
||||||
|
except (KeyboardInterrupt, SystemExit):
|
||||||
|
raise
|
||||||
|
except:
|
||||||
|
failure = py.std.sys.exc_info()
|
||||||
|
setattr(self, exattrname, failure)
|
||||||
|
raise
|
||||||
|
setattr(self, attrname, res)
|
||||||
|
return res
|
||||||
|
|
||||||
def listchain(self):
|
def listchain(self):
|
||||||
""" return list of all parent collectors up to self. """
|
""" return list of all parent collectors up to self. """
|
||||||
l = [self]
|
l = [self]
|
||||||
|
@ -173,7 +191,7 @@ class Node(object):
|
||||||
if name:
|
if name:
|
||||||
next = cur.join(name)
|
next = cur.join(name)
|
||||||
if next is None:
|
if next is None:
|
||||||
existingnames = cur.listdir()
|
existingnames = [x.name for x in self._memocollect()]
|
||||||
msg = ("Collector %r does not have name %r "
|
msg = ("Collector %r does not have name %r "
|
||||||
"existing names are: %s" %
|
"existing names are: %s" %
|
||||||
(cur, name, existingnames))
|
(cur, name, existingnames))
|
||||||
|
@ -262,9 +280,8 @@ class Node(object):
|
||||||
|
|
||||||
class Collector(Node):
|
class Collector(Node):
|
||||||
"""
|
"""
|
||||||
Collector instances generate children through
|
Collector instances create children through collect()
|
||||||
their listdir() and join() methods and thus
|
and thus iteratively build a tree. attributes::
|
||||||
form a tree. attributes::
|
|
||||||
|
|
||||||
parent: attribute pointing to the parent collector
|
parent: attribute pointing to the parent collector
|
||||||
(or None if this is the root collector)
|
(or None if this is the root collector)
|
||||||
|
@ -274,31 +291,60 @@ class Collector(Node):
|
||||||
Module = configproperty('Module')
|
Module = configproperty('Module')
|
||||||
DoctestFile = configproperty('DoctestFile')
|
DoctestFile = configproperty('DoctestFile')
|
||||||
|
|
||||||
def run(self):
|
def collect(self):
|
||||||
""" deprecated: use listdir(). """
|
""" returns a list of children (items and collectors)
|
||||||
py.std.warnings.warn("deprecated: use listdir()", category=DeprecationWarning)
|
for this collection node.
|
||||||
return self.listdir()
|
|
||||||
|
|
||||||
def multijoin(self, namelist):
|
|
||||||
""" return a list of colitems for the given namelist. """
|
|
||||||
return [self.join(name) for name in namelist]
|
|
||||||
|
|
||||||
def listdir(self):
|
|
||||||
""" returns a list of names available from this collector.
|
|
||||||
You can return an empty list. Callers of this method
|
|
||||||
must take care to catch exceptions properly.
|
|
||||||
"""
|
|
||||||
raise NotImplementedError("abstract")
|
|
||||||
|
|
||||||
def join(self, name):
|
|
||||||
""" return a child collector or item for the given name.
|
|
||||||
If the return value is None there is no such child.
|
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError("abstract")
|
raise NotImplementedError("abstract")
|
||||||
|
|
||||||
def repr_failure(self, excinfo, outerr):
|
def repr_failure(self, excinfo, outerr):
|
||||||
|
""" represent a failure. """
|
||||||
return self._repr_failure_py(excinfo, outerr)
|
return self._repr_failure_py(excinfo, outerr)
|
||||||
|
|
||||||
|
def _memocollect(self):
|
||||||
|
""" internal helper method to cache results of calling collect(). """
|
||||||
|
return self._memoizedcall('_collected', self.collect)
|
||||||
|
|
||||||
|
# **********************************************************************
|
||||||
|
# DEPRECATED METHODS
|
||||||
|
# **********************************************************************
|
||||||
|
|
||||||
|
def _deprecated_collect(self):
|
||||||
|
# avoid recursion:
|
||||||
|
# collect -> _deprecated_collect -> custom run() ->
|
||||||
|
# super().run() -> collect
|
||||||
|
attrname = '_depcollectentered'
|
||||||
|
if hasattr(self, attrname):
|
||||||
|
return
|
||||||
|
setattr(self, attrname, True)
|
||||||
|
method = getattr(self.__class__, 'run', None)
|
||||||
|
if method is not None and method != Collector.run:
|
||||||
|
warnoldcollect()
|
||||||
|
names = self.run()
|
||||||
|
return filter(None, [self.join(name) for name in names])
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
""" DEPRECATED: returns a list of names available from this collector.
|
||||||
|
You can return an empty list. Callers of this method
|
||||||
|
must take care to catch exceptions properly.
|
||||||
|
"""
|
||||||
|
warnoldcollect()
|
||||||
|
return [colitem.name for colitem in self._memocollect()]
|
||||||
|
|
||||||
|
def join(self, name):
|
||||||
|
""" DEPRECATED: return a child collector or item for the given name.
|
||||||
|
If the return value is None there is no such child.
|
||||||
|
"""
|
||||||
|
warnoldcollect()
|
||||||
|
for colitem in self._memocollect():
|
||||||
|
if colitem.name == name:
|
||||||
|
return colitem
|
||||||
|
|
||||||
|
def multijoin(self, namelist):
|
||||||
|
""" DEPRECATED: return a list of colitems for the given namelist. """
|
||||||
|
warnoldcollect()
|
||||||
|
return [self.join(name) for name in namelist]
|
||||||
|
|
||||||
class FSCollector(Collector):
|
class FSCollector(Collector):
|
||||||
def __init__(self, fspath, parent=None, config=None):
|
def __init__(self, fspath, parent=None, config=None):
|
||||||
fspath = py.path.local(fspath)
|
fspath = py.path.local(fspath)
|
||||||
|
@ -336,49 +382,53 @@ class FSCollector(Collector):
|
||||||
|
|
||||||
|
|
||||||
class Directory(FSCollector):
|
class Directory(FSCollector):
|
||||||
def filefilter(self, path):
|
|
||||||
if path.check(file=1):
|
|
||||||
b = path.purebasename
|
|
||||||
ext = path.ext
|
|
||||||
return (b.startswith('test_') or
|
|
||||||
b.endswith('_test')) and ext in ('.txt', '.py')
|
|
||||||
|
|
||||||
def recfilter(self, path):
|
def recfilter(self, path):
|
||||||
if path.check(dir=1, dotfile=0):
|
if path.check(dir=1, dotfile=0):
|
||||||
return path.basename not in ('CVS', '_darcs', '{arch}')
|
return path.basename not in ('CVS', '_darcs', '{arch}')
|
||||||
|
|
||||||
def listdir(self):
|
def collect(self):
|
||||||
files = []
|
l = self._deprecated_collect()
|
||||||
dirs = []
|
if l is not None:
|
||||||
for p in self.fspath.listdir():
|
return l
|
||||||
if self.filefilter(p):
|
l = []
|
||||||
files.append(p.basename)
|
for path in self.fspath.listdir(): # listdir() returns sorted order
|
||||||
elif self.recfilter(p):
|
res = self.consider(path, usefilters=True)
|
||||||
dirs.append(p.basename)
|
if res is not None:
|
||||||
files.sort()
|
l.append(res)
|
||||||
dirs.sort()
|
return l
|
||||||
return files + dirs
|
|
||||||
|
def consider(self, path, usefilters=True):
|
||||||
|
print "checking", path
|
||||||
|
if path.check(file=1):
|
||||||
|
return self.consider_file(path, usefilters=usefilters)
|
||||||
|
elif path.check(dir=1):
|
||||||
|
return self.consider_dir(path, usefilters=usefilters)
|
||||||
|
|
||||||
|
def consider_file(self, path, usefilters=True):
|
||||||
|
ext = path.ext
|
||||||
|
pb = path.purebasename
|
||||||
|
if not usefilters or pb.startswith("test_") or pb.endswith("_test"):
|
||||||
|
if ext == ".py":
|
||||||
|
return self.Module(path, parent=self)
|
||||||
|
elif ext == ".txt":
|
||||||
|
return self.DoctestFile(path, parent=self)
|
||||||
|
|
||||||
|
def consider_dir(self, path, usefilters=True):
|
||||||
|
if not usefilters or self.recfilter(path):
|
||||||
|
# not use self.Directory here as
|
||||||
|
# dir/conftest.py shall be able to
|
||||||
|
# define Directory(dir) already
|
||||||
|
Directory = self._config.getvalue('Directory', path)
|
||||||
|
return Directory(path, parent=self)
|
||||||
|
|
||||||
|
# **********************************************************************
|
||||||
|
# DEPRECATED METHODS
|
||||||
|
# **********************************************************************
|
||||||
|
|
||||||
def join(self, name):
|
def join(self, name):
|
||||||
name2items = self.__dict__.setdefault('_name2items', {})
|
""" get a child collector or item without using filters. """
|
||||||
try:
|
p = self.fspath.join(name)
|
||||||
res = name2items[name]
|
return self.consider(p, usefilters=False)
|
||||||
except KeyError:
|
|
||||||
p = self.fspath.join(name)
|
|
||||||
res = None
|
|
||||||
if p.check(file=1):
|
|
||||||
if p.ext == '.py':
|
|
||||||
res = self.Module(p, parent=self)
|
|
||||||
elif p.ext == '.txt':
|
|
||||||
res = self.DoctestFile(p, parent=self)
|
|
||||||
elif p.check(dir=1):
|
|
||||||
# not use self.Directory here as
|
|
||||||
# dir/conftest.py shall be able to
|
|
||||||
# define Directory(dir) already
|
|
||||||
Directory = self._config.getvalue('Directory', p)
|
|
||||||
res = Directory(p, parent=self)
|
|
||||||
name2items[name] = res
|
|
||||||
return res
|
|
||||||
|
|
||||||
from py.__.test.runner import basic_run_report, forked_run_report
|
from py.__.test.runner import basic_run_report, forked_run_report
|
||||||
class Item(Node):
|
class Item(Node):
|
||||||
|
@ -388,6 +438,24 @@ class Item(Node):
|
||||||
return forked_run_report
|
return forked_run_report
|
||||||
return basic_run_report
|
return basic_run_report
|
||||||
|
|
||||||
|
def _deprecated_testexecution(self):
|
||||||
|
if self.__class__.run != Item.run:
|
||||||
|
warnoldtestrun()
|
||||||
|
self.run()
|
||||||
|
return True
|
||||||
|
elif self.__class__.execute != Item.execute:
|
||||||
|
warnoldtestrun()
|
||||||
|
self.execute(self.obj, *self._args)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
warnoldtestrun()
|
||||||
|
return self.execute(self.obj, *self._args)
|
||||||
|
|
||||||
|
def execute(self, obj, *args):
|
||||||
|
warnoldtestrun()
|
||||||
|
return obj(*args)
|
||||||
|
|
||||||
def repr_metainfo(self):
|
def repr_metainfo(self):
|
||||||
try:
|
try:
|
||||||
return self.ReprMetaInfo(self.fspath, modpath=self.__class__.__name__)
|
return self.ReprMetaInfo(self.fspath, modpath=self.__class__.__name__)
|
||||||
|
@ -395,7 +463,7 @@ class Item(Node):
|
||||||
code = py.code.Code(self.execute)
|
code = py.code.Code(self.execute)
|
||||||
return self.ReprMetaInfo(code.path, code.firstlineno)
|
return self.ReprMetaInfo(code.path, code.firstlineno)
|
||||||
|
|
||||||
def execute(self):
|
def runtest(self):
|
||||||
""" execute this test item."""
|
""" execute this test item."""
|
||||||
|
|
||||||
|
|
||||||
|
@ -417,3 +485,13 @@ def getrelpath(curdir, dest):
|
||||||
return target
|
return target
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return dest
|
return dest
|
||||||
|
|
||||||
|
|
||||||
|
def depwarn(msg):
|
||||||
|
py.std.warnings.warn(msg, DeprecationWarning)
|
||||||
|
|
||||||
|
def warnoldcollect():
|
||||||
|
return depwarn("implement collector.collect() instead of collector.run() and collector.join()")
|
||||||
|
|
||||||
|
def warnoldtestrun():
|
||||||
|
return depwarn("implement item.runtest() instead of item.run() and item.execute()")
|
||||||
|
|
|
@ -6,7 +6,7 @@ class TestCaseUnit(Function):
|
||||||
""" compatibility Unit executor for TestCase methods
|
""" compatibility Unit executor for TestCase methods
|
||||||
honouring setUp and tearDown semantics.
|
honouring setUp and tearDown semantics.
|
||||||
"""
|
"""
|
||||||
def execute(self, _deprecated=None):
|
def runtest(self, _deprecated=None):
|
||||||
boundmethod = self.obj
|
boundmethod = self.obj
|
||||||
instance = boundmethod.im_self
|
instance = boundmethod.im_self
|
||||||
instance.setUp()
|
instance.setUp()
|
||||||
|
|
|
@ -15,7 +15,7 @@ class DirSetup(object):
|
||||||
|
|
||||||
class BasicRsessionTest(object):
|
class BasicRsessionTest(object):
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
path = getexamplefile("funcexamples.py")
|
path = getexamplefile("test_funcexamples.py")
|
||||||
cls.config = py.test.config._reparse([path.dirpath()])
|
cls.config = py.test.config._reparse([path.dirpath()])
|
||||||
cls.modulecol = cls.config.getfsnode(path)
|
cls.modulecol = cls.config.getfsnode(path)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ class BasicRsessionTest(object):
|
||||||
self.session = self.config.initsession()
|
self.session = self.config.initsession()
|
||||||
|
|
||||||
def getfunc(self, name):
|
def getfunc(self, name):
|
||||||
funcname = "func" + name
|
funcname = "test_func" + name
|
||||||
col = self.modulecol.join(funcname)
|
col = self.modulecol.join(funcname)
|
||||||
assert col is not None, funcname
|
assert col is not None, funcname
|
||||||
return col
|
return col
|
||||||
|
|
|
@ -157,7 +157,7 @@ class TestDSession(InlineCollection):
|
||||||
def test_fail():
|
def test_fail():
|
||||||
x
|
x
|
||||||
""")
|
""")
|
||||||
item1, item2 = [modcol.join(x) for x in modcol.listdir()]
|
item1, item2 = modcol.collect()
|
||||||
|
|
||||||
# setup a session with two hosts
|
# setup a session with two hosts
|
||||||
session = DSession(item1._config)
|
session = DSession(item1._config)
|
||||||
|
@ -295,7 +295,7 @@ class TestDSession(InlineCollection):
|
||||||
modcol._config.option.keyword = "nothing"
|
modcol._config.option.keyword = "nothing"
|
||||||
dsel = session.filteritems([modcol])
|
dsel = session.filteritems([modcol])
|
||||||
assert dsel == [modcol]
|
assert dsel == [modcol]
|
||||||
items = [modcol.join(x) for x in modcol.listdir()]
|
items = modcol.collect()
|
||||||
events = [] ; session.bus.subscribe(events.append)
|
events = [] ; session.bus.subscribe(events.append)
|
||||||
remaining = session.filteritems(items)
|
remaining = session.filteritems(items)
|
||||||
assert remaining == []
|
assert remaining == []
|
||||||
|
|
|
@ -118,7 +118,7 @@ def deprecated_call(func, *args, **kwargs):
|
||||||
warningmodule.warn_explicit = warn_explicit
|
warningmodule.warn_explicit = warn_explicit
|
||||||
warningmodule.warn = warn
|
warningmodule.warn = warn
|
||||||
if not l:
|
if not l:
|
||||||
print warningmodule
|
#print warningmodule
|
||||||
raise AssertionError("%r did not produce DeprecationWarning" %(func,))
|
raise AssertionError("%r did not produce DeprecationWarning" %(func,))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ a tree of collectors and test items that this modules provides::
|
||||||
"""
|
"""
|
||||||
import py
|
import py
|
||||||
from py.__.test.collect import Collector, FSCollector, Item, configproperty
|
from py.__.test.collect import Collector, FSCollector, Item, configproperty
|
||||||
|
from py.__.test.collect import warnoldcollect
|
||||||
|
|
||||||
class PyobjMixin(object):
|
class PyobjMixin(object):
|
||||||
def obj():
|
def obj():
|
||||||
|
@ -96,6 +97,15 @@ class PyCollectorMixin(PyobjMixin, Collector):
|
||||||
def classnamefilter(self, name):
|
def classnamefilter(self, name):
|
||||||
return name.startswith('Test')
|
return name.startswith('Test')
|
||||||
|
|
||||||
|
def collect(self):
|
||||||
|
l = self._deprecated_collect()
|
||||||
|
if l is not None:
|
||||||
|
return l
|
||||||
|
name2items = self._buildname2items()
|
||||||
|
colitems = name2items.values()
|
||||||
|
colitems.sort()
|
||||||
|
return colitems
|
||||||
|
|
||||||
def _buildname2items(self):
|
def _buildname2items(self):
|
||||||
# NB. we avoid random getattrs and peek in the __dict__ instead
|
# NB. we avoid random getattrs and peek in the __dict__ instead
|
||||||
d = {}
|
d = {}
|
||||||
|
@ -113,67 +123,37 @@ class PyCollectorMixin(PyobjMixin, Collector):
|
||||||
d[name] = res
|
d[name] = res
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
def _deprecated_join(self, name):
|
||||||
|
if self.__class__.join != py.test.collect.Collector.join:
|
||||||
|
warnoldcollect()
|
||||||
|
return self.join(name)
|
||||||
|
|
||||||
def makeitem(self, name, obj, usefilters=True):
|
def makeitem(self, name, obj, usefilters=True):
|
||||||
if (not usefilters or self.classnamefilter(name)) and \
|
if (not usefilters or self.classnamefilter(name)) and \
|
||||||
py.std.inspect.isclass(obj):
|
py.std.inspect.isclass(obj):
|
||||||
|
res = self._deprecated_join(name)
|
||||||
|
if res is not None:
|
||||||
|
return res
|
||||||
return self.Class(name, parent=self)
|
return self.Class(name, parent=self)
|
||||||
elif (not usefilters or self.funcnamefilter(name)) and callable(obj):
|
elif (not usefilters or self.funcnamefilter(name)) and callable(obj):
|
||||||
|
res = self._deprecated_join(name)
|
||||||
|
if res is not None:
|
||||||
|
return res
|
||||||
if obj.func_code.co_flags & 32: # generator function
|
if obj.func_code.co_flags & 32: # generator function
|
||||||
return self.Generator(name, parent=self)
|
return self.Generator(name, parent=self)
|
||||||
else:
|
else:
|
||||||
return self.Function(name, parent=self)
|
return self.Function(name, parent=self)
|
||||||
|
|
||||||
def _prepare(self):
|
|
||||||
if not hasattr(self, '_name2items'):
|
|
||||||
ex = getattr(self, '_name2items_exception', None)
|
|
||||||
if ex is not None:
|
|
||||||
raise ex[0], ex[1], ex[2]
|
|
||||||
try:
|
|
||||||
self._name2items = self._buildname2items()
|
|
||||||
except (SystemExit, KeyboardInterrupt):
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
self._name2items_exception = py.std.sys.exc_info()
|
|
||||||
raise
|
|
||||||
|
|
||||||
def listdir(self):
|
|
||||||
self._prepare()
|
|
||||||
itemlist = self._name2items.values()
|
|
||||||
itemlist.sort()
|
|
||||||
return [x.name for x in itemlist]
|
|
||||||
|
|
||||||
def join(self, name):
|
|
||||||
self._prepare()
|
|
||||||
return self._name2items.get(name, None)
|
|
||||||
|
|
||||||
class Module(FSCollector, PyCollectorMixin):
|
class Module(FSCollector, PyCollectorMixin):
|
||||||
_stickyfailure = None
|
_stickyfailure = None
|
||||||
|
|
||||||
def listdir(self):
|
def collect(self):
|
||||||
if getattr(self.obj, 'disabled', 0):
|
if getattr(self.obj, 'disabled', 0):
|
||||||
return []
|
return []
|
||||||
return super(Module, self).listdir()
|
return super(Module, self).collect()
|
||||||
|
|
||||||
def join(self, name):
|
|
||||||
res = super(Module, self).join(name)
|
|
||||||
if res is None:
|
|
||||||
attr = getattr(self.obj, name, None)
|
|
||||||
if attr is not None:
|
|
||||||
res = self.makeitem(name, attr, usefilters=False)
|
|
||||||
return res
|
|
||||||
|
|
||||||
def _getobj(self):
|
def _getobj(self):
|
||||||
failure = self._stickyfailure
|
return self._memoizedcall('_obj', self.fspath.pyimport)
|
||||||
if failure is not None:
|
|
||||||
raise failure[0], failure[1], failure[2]
|
|
||||||
try:
|
|
||||||
self._obj = obj = self.fspath.pyimport()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
self._stickyfailure = py.std.sys.exc_info()
|
|
||||||
raise
|
|
||||||
return self._obj
|
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
if not self._config.option.nomagic:
|
if not self._config.option.nomagic:
|
||||||
|
@ -191,14 +171,13 @@ class Module(FSCollector, PyCollectorMixin):
|
||||||
|
|
||||||
class Class(PyCollectorMixin, Collector):
|
class Class(PyCollectorMixin, Collector):
|
||||||
|
|
||||||
def listdir(self):
|
def collect(self):
|
||||||
if getattr(self.obj, 'disabled', 0):
|
if getattr(self.obj, 'disabled', 0):
|
||||||
return []
|
return []
|
||||||
return ["()"]
|
l = self._deprecated_collect()
|
||||||
|
if l is not None:
|
||||||
def join(self, name):
|
return l
|
||||||
assert name == '()'
|
return [self.Instance(name="()", parent=self)]
|
||||||
return self.Instance(name, self)
|
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
setup_class = getattr(self.obj, 'setup_class', None)
|
setup_class = getattr(self.obj, 'setup_class', None)
|
||||||
|
@ -215,7 +194,6 @@ class Class(PyCollectorMixin, Collector):
|
||||||
def _getsortvalue(self):
|
def _getsortvalue(self):
|
||||||
return self.getfslineno()
|
return self.getfslineno()
|
||||||
|
|
||||||
|
|
||||||
class Instance(PyCollectorMixin, Collector):
|
class Instance(PyCollectorMixin, Collector):
|
||||||
def _getobj(self):
|
def _getobj(self):
|
||||||
return self.parent.obj()
|
return self.parent.obj()
|
||||||
|
@ -226,6 +204,10 @@ class Instance(PyCollectorMixin, Collector):
|
||||||
return []
|
return []
|
||||||
Function = property(Function)
|
Function = property(Function)
|
||||||
|
|
||||||
|
#def __repr__(self):
|
||||||
|
# return "<%s of '%s'>" %(self.__class__.__name__,
|
||||||
|
# self.parent.obj.__name__)
|
||||||
|
|
||||||
def newinstance(self):
|
def newinstance(self):
|
||||||
self.obj = self._getobj()
|
self.obj = self._getobj()
|
||||||
return self.obj
|
return self.obj
|
||||||
|
@ -278,24 +260,19 @@ class FunctionMixin(PyobjMixin):
|
||||||
shortfailurerepr = "F"
|
shortfailurerepr = "F"
|
||||||
|
|
||||||
class Generator(FunctionMixin, PyCollectorMixin, Collector):
|
class Generator(FunctionMixin, PyCollectorMixin, Collector):
|
||||||
def listdir(self):
|
def collect(self):
|
||||||
self._prepare()
|
# test generators are collectors yet participate in
|
||||||
itemlist = self._name2items
|
# the test-item setup and teardown protocol.
|
||||||
return [itemlist["[%d]" % num].name for num in xrange(len(itemlist))]
|
# otherwise we could avoid global setupstate
|
||||||
|
|
||||||
def _buildname2items(self):
|
|
||||||
d = {}
|
|
||||||
# XXX test generators are collectors yet participate in
|
|
||||||
# the test-item setup and teardown protocol
|
|
||||||
# if not for this we could probably avoid global setupstate
|
|
||||||
self._setupstate.prepare(self)
|
self._setupstate.prepare(self)
|
||||||
|
l = []
|
||||||
for i, x in py.builtin.enumerate(self.obj()):
|
for i, x in py.builtin.enumerate(self.obj()):
|
||||||
call, args = self.getcallargs(x)
|
call, args = self.getcallargs(x)
|
||||||
if not callable(call):
|
if not callable(call):
|
||||||
raise TypeError("%r yielded non callable test %r" %(self.obj, call,))
|
raise TypeError("%r yielded non callable test %r" %(self.obj, call,))
|
||||||
name = "[%d]" % i
|
name = "[%d]" % i
|
||||||
d[name] = self.Function(name, self, args=args, callobj=call)
|
l.append(self.Function(name, self, args=args, callobj=call))
|
||||||
return d
|
return l
|
||||||
|
|
||||||
def getcallargs(self, obj):
|
def getcallargs(self, obj):
|
||||||
if isinstance(obj, (tuple, list)):
|
if isinstance(obj, (tuple, list)):
|
||||||
|
@ -318,9 +295,10 @@ class Function(FunctionMixin, Item):
|
||||||
if callobj is not _dummy:
|
if callobj is not _dummy:
|
||||||
self._obj = callobj
|
self._obj = callobj
|
||||||
|
|
||||||
def execute(self):
|
def runtest(self):
|
||||||
""" execute the given test function. """
|
""" execute the given test function. """
|
||||||
self.obj(*self._args)
|
if not self._deprecated_testexecution():
|
||||||
|
self.obj(*self._args)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
try:
|
try:
|
||||||
|
@ -335,12 +313,9 @@ class Function(FunctionMixin, Item):
|
||||||
return not self == other
|
return not self == other
|
||||||
|
|
||||||
class DoctestFile(FSCollector):
|
class DoctestFile(FSCollector):
|
||||||
def listdir(self):
|
|
||||||
return [self.fspath.basename]
|
def collect(self):
|
||||||
|
return [DoctestFileContent(self.fspath.basename, parent=self)]
|
||||||
def join(self, name):
|
|
||||||
if name == self.fspath.basename:
|
|
||||||
return DoctestFileContent(name, self)
|
|
||||||
|
|
||||||
from py.__.code.excinfo import Repr, ReprFileLocation
|
from py.__.code.excinfo import Repr, ReprFileLocation
|
||||||
|
|
||||||
|
@ -378,8 +353,9 @@ class DoctestFileContent(Item):
|
||||||
else:
|
else:
|
||||||
return super(DoctestFileContent, self).repr_failure(excinfo, outerr)
|
return super(DoctestFileContent, self).repr_failure(excinfo, outerr)
|
||||||
|
|
||||||
def execute(self):
|
def runtest(self):
|
||||||
failed, tot = py.compat.doctest.testfile(
|
if not self._deprecated_testexecution():
|
||||||
str(self.fspath), module_relative=False,
|
failed, tot = py.compat.doctest.testfile(
|
||||||
raise_on_error=True, verbose=0)
|
str(self.fspath), module_relative=False,
|
||||||
|
raise_on_error=True, verbose=0)
|
||||||
|
|
||||||
|
|
|
@ -86,10 +86,10 @@ def test_getmodpath_cases():
|
||||||
assert getmodpath(fcol) == expected
|
assert getmodpath(fcol) == expected
|
||||||
|
|
||||||
for names in (
|
for names in (
|
||||||
'mod.py test_f1 mod.test_f1',
|
'test_mod.py test_f1 test_mod.test_f1',
|
||||||
'mod.py TestA () test_m1 mod.TestA().test_m1',
|
'test_mod.py TestA () test_m1 test_mod.TestA().test_m1',
|
||||||
'mod.py test_g1 mod.test_g1',
|
'test_mod.py test_g1 test_mod.test_g1',
|
||||||
'mod.py test_g1 [0] mod.test_g1[0]',
|
'test_mod.py test_g1 [0] test_mod.test_g1[0]',
|
||||||
):
|
):
|
||||||
names = names.split()
|
names = names.split()
|
||||||
expected = names.pop()
|
expected = names.pop()
|
||||||
|
|
|
@ -15,7 +15,7 @@ class TestCollectonly(InlineCollection):
|
||||||
indent = rep.indent
|
indent = rep.indent
|
||||||
rep.processevent(event.CollectionStart(modcol))
|
rep.processevent(event.CollectionStart(modcol))
|
||||||
s = popvalue(stringio)
|
s = popvalue(stringio)
|
||||||
assert s == "<Module 'TestCollectonly_test_collectonly_basic.py'>"
|
assert s == "<Module 'test_TestCollectonly_test_collectonly_basic.py'>"
|
||||||
|
|
||||||
item = modcol.join("test_func")
|
item = modcol.join("test_func")
|
||||||
rep.processevent(event.ItemStart(item))
|
rep.processevent(event.ItemStart(item))
|
||||||
|
@ -34,7 +34,7 @@ class TestCollectonly(InlineCollection):
|
||||||
cols = list(self.session.genitems([modcol]))
|
cols = list(self.session.genitems([modcol]))
|
||||||
assert len(cols) == 0
|
assert len(cols) == 0
|
||||||
assert_stringio_contains_lines(stringio, """
|
assert_stringio_contains_lines(stringio, """
|
||||||
<Module 'TestCollectonly_test_collectonly_skipped_module.py'>
|
<Module 'test_TestCollectonly_test_collectonly_skipped_module.py'>
|
||||||
!!! Skipped: 'nomod' !!!
|
!!! Skipped: 'nomod' !!!
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class TestCollectonly(InlineCollection):
|
||||||
cols = list(self.session.genitems([modcol]))
|
cols = list(self.session.genitems([modcol]))
|
||||||
assert len(cols) == 0
|
assert len(cols) == 0
|
||||||
assert_stringio_contains_lines(stringio, """
|
assert_stringio_contains_lines(stringio, """
|
||||||
<Module 'TestCollectonly_test_collectonly_failed_module.py'>
|
<Module 'test_TestCollectonly_test_collectonly_failed_module.py'>
|
||||||
!!! ValueError: 0 !!!
|
!!! ValueError: 0 !!!
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ class TestTerminal(InlineCollection):
|
||||||
stringio = py.std.cStringIO.StringIO()
|
stringio = py.std.cStringIO.StringIO()
|
||||||
rep = TerminalReporter(modcol._config, file=stringio)
|
rep = TerminalReporter(modcol._config, file=stringio)
|
||||||
rep.processevent(event.TestrunStart())
|
rep.processevent(event.TestrunStart())
|
||||||
items = [modcol.join(x) for x in modcol.listdir()]
|
items = modcol.collect()
|
||||||
for item in items:
|
for item in items:
|
||||||
rep.processevent(event.ItemStart(item))
|
rep.processevent(event.ItemStart(item))
|
||||||
s = stringio.getvalue().strip()
|
s = stringio.getvalue().strip()
|
||||||
|
@ -153,8 +153,7 @@ class TestTerminal(InlineCollection):
|
||||||
""")
|
""")
|
||||||
stringio = py.std.cStringIO.StringIO()
|
stringio = py.std.cStringIO.StringIO()
|
||||||
rep = TerminalReporter(modcol._config, file=stringio)
|
rep = TerminalReporter(modcol._config, file=stringio)
|
||||||
reports = [basic_run_report(modcol.join(x))
|
reports = [basic_run_report(x) for x in modcol.collect()]
|
||||||
for x in modcol.listdir()]
|
|
||||||
rep.processevent(event.LooponfailingInfo(reports, [modcol._config.topdir]))
|
rep.processevent(event.LooponfailingInfo(reports, [modcol._config.topdir]))
|
||||||
assert_stringio_contains_lines(stringio, [
|
assert_stringio_contains_lines(stringio, [
|
||||||
"*test_looponfailingreport.py:2: assert 0",
|
"*test_looponfailingreport.py:2: assert 0",
|
||||||
|
|
|
@ -68,7 +68,7 @@ class ItemRunner(RobustRun):
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
self.colitem._setupstate.teardown_exact(self.colitem)
|
self.colitem._setupstate.teardown_exact(self.colitem)
|
||||||
def execute(self):
|
def execute(self):
|
||||||
self.colitem.execute()
|
self.colitem.runtest()
|
||||||
def makereport(self, res, when, excinfo, outerr):
|
def makereport(self, res, when, excinfo, outerr):
|
||||||
if excinfo:
|
if excinfo:
|
||||||
kw = self.getkw(when, excinfo, outerr)
|
kw = self.getkw(when, excinfo, outerr)
|
||||||
|
@ -84,7 +84,7 @@ class CollectorRunner(RobustRun):
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
pass
|
pass
|
||||||
def execute(self):
|
def execute(self):
|
||||||
return [self.colitem.join(x) for x in self.colitem.listdir()]
|
return self.colitem._memocollect()
|
||||||
def makereport(self, res, when, excinfo, outerr):
|
def makereport(self, res, when, excinfo, outerr):
|
||||||
if excinfo:
|
if excinfo:
|
||||||
kw = self.getkw(when, excinfo, outerr)
|
kw = self.getkw(when, excinfo, outerr)
|
||||||
|
|
|
@ -211,7 +211,7 @@ class TestPyTest(AcceptBase):
|
||||||
""")
|
""")
|
||||||
result = self.runpytest(p1)
|
result = self.runpytest(p1)
|
||||||
assert_lines_contain_lines(result.outlines, [
|
assert_lines_contain_lines(result.outlines, [
|
||||||
"test_fail.py F",
|
".*test_fail.py F",
|
||||||
"====* FAILURES *====",
|
"====* FAILURES *====",
|
||||||
"____*____",
|
"____*____",
|
||||||
"",
|
"",
|
||||||
|
@ -242,7 +242,7 @@ class TestPyTest(AcceptBase):
|
||||||
""")
|
""")
|
||||||
result = self.runpytest(p1)
|
result = self.runpytest(p1)
|
||||||
assert_lines_contain_lines(result.outlines, [
|
assert_lines_contain_lines(result.outlines, [
|
||||||
"test_one.py .F",
|
".*test_one.py .F",
|
||||||
"====* FAILURES *====",
|
"====* FAILURES *====",
|
||||||
"____*____",
|
"____*____",
|
||||||
"*test_one.py:8: ValueError",
|
"*test_one.py:8: ValueError",
|
||||||
|
|
|
@ -81,7 +81,7 @@ namecontent = {
|
||||||
|
|
||||||
'failingimport.py': "import gruetzelmuetzel\n",
|
'failingimport.py': "import gruetzelmuetzel\n",
|
||||||
|
|
||||||
'mod.py': """
|
'test_mod.py': """
|
||||||
class TestA:
|
class TestA:
|
||||||
def test_m1(self):
|
def test_m1(self):
|
||||||
pass
|
pass
|
||||||
|
@ -91,7 +91,7 @@ namecontent = {
|
||||||
yield lambda x: None, 42
|
yield lambda x: None, 42
|
||||||
""",
|
""",
|
||||||
|
|
||||||
'filetest.py': """
|
'file_test.py': """
|
||||||
def test_one():
|
def test_one():
|
||||||
assert 42 == 43
|
assert 42 == 43
|
||||||
|
|
||||||
|
@ -125,60 +125,45 @@ namecontent = {
|
||||||
pass
|
pass
|
||||||
""",
|
""",
|
||||||
|
|
||||||
'funcexamples.py': """
|
'test_funcexamples.py': """
|
||||||
import py
|
import py
|
||||||
import time
|
import time
|
||||||
def funcpassed():
|
def test_funcpassed():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def funcfailed():
|
def test_funcfailed():
|
||||||
raise AssertionError("hello world")
|
raise AssertionError("hello world")
|
||||||
|
|
||||||
def funcskipped():
|
def test_funcskipped():
|
||||||
py.test.skip("skipped")
|
py.test.skip("skipped")
|
||||||
|
|
||||||
def funcprint():
|
def test_funcprint():
|
||||||
print "samfing"
|
print "samfing"
|
||||||
|
|
||||||
def funcprinterr():
|
def test_funcprinterr():
|
||||||
print >>py.std.sys.stderr, "samfing"
|
print >>py.std.sys.stderr, "samfing"
|
||||||
|
|
||||||
def funcprintfail():
|
def test_funcprintfail():
|
||||||
print "samfing elz"
|
print "samfing elz"
|
||||||
asddsa
|
asddsa
|
||||||
|
|
||||||
def funcexplicitfail():
|
def test_funcexplicitfail():
|
||||||
py.test.fail("3")
|
py.test.fail("3")
|
||||||
|
|
||||||
def funcraisesfails():
|
def test_funcraisesfails():
|
||||||
py.test.raises(ValueError, lambda: 123)
|
py.test.raises(ValueError, lambda: 123)
|
||||||
|
|
||||||
def funcoptioncustom():
|
def test_funcoptioncustom():
|
||||||
assert py.test.config.getvalue("custom")
|
assert py.test.config.getvalue("custom")
|
||||||
|
|
||||||
def funchang():
|
def test_funchang():
|
||||||
import time
|
import time
|
||||||
time.sleep(1000)
|
time.sleep(1000)
|
||||||
|
|
||||||
def funckill15():
|
def test_funckill15():
|
||||||
import os
|
import os
|
||||||
os.kill(os.getpid(), 15)
|
os.kill(os.getpid(), 15)
|
||||||
""",
|
""",
|
||||||
|
|
||||||
'test_generative.py': """
|
|
||||||
from __future__ import generators # python2.2!
|
|
||||||
def func1(arg, arg2):
|
|
||||||
assert arg == arg2
|
|
||||||
|
|
||||||
def test_gen():
|
|
||||||
yield func1, 17, 3*5
|
|
||||||
yield func1, 42, 6*7
|
|
||||||
|
|
||||||
class TestGenMethods:
|
|
||||||
def test_gen(self):
|
|
||||||
yield func1, 17, 3*5
|
|
||||||
yield func1, 42, 6*7
|
|
||||||
""",
|
|
||||||
|
|
||||||
'docexample.txt': """
|
'docexample.txt': """
|
||||||
Aha!!!!!!
|
Aha!!!!!!
|
||||||
|
@ -186,56 +171,3 @@ namecontent = {
|
||||||
""",
|
""",
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def setup_customconfigtest(tmpdir):
|
|
||||||
o = tmpdir.ensure('customconfigtest', dir=1)
|
|
||||||
o.ensure('conftest.py').write("""if 1:
|
|
||||||
import py
|
|
||||||
class MyFunction(py.test.collect.Function):
|
|
||||||
pass
|
|
||||||
class Directory(py.test.collect.Directory):
|
|
||||||
def filefilter(self, fspath):
|
|
||||||
return fspath.check(basestarts='check_', ext='.py')
|
|
||||||
class myfuncmixin:
|
|
||||||
Function = MyFunction
|
|
||||||
def funcnamefilter(self, name):
|
|
||||||
return name.startswith('check_')
|
|
||||||
|
|
||||||
class Module(myfuncmixin, py.test.collect.Module):
|
|
||||||
def classnamefilter(self, name):
|
|
||||||
return name.startswith('CustomTestClass')
|
|
||||||
class Instance(myfuncmixin, py.test.collect.Instance):
|
|
||||||
pass
|
|
||||||
""")
|
|
||||||
checkfile = o.ensure('somedir', 'check_something.py')
|
|
||||||
checkfile.write("""if 1:
|
|
||||||
def check_func():
|
|
||||||
assert 42 == 42
|
|
||||||
class CustomTestClass:
|
|
||||||
def check_method(self):
|
|
||||||
assert 23 == 23
|
|
||||||
""")
|
|
||||||
return checkfile
|
|
||||||
|
|
||||||
def setup_non_python_dir(tmpdir):
|
|
||||||
o = tmpdir.ensure('customconfigtest_nonpython', dir=1)
|
|
||||||
o.ensure('conftest.py').write("""if 1:
|
|
||||||
import py
|
|
||||||
class CustomItem(py.test.collect.Item):
|
|
||||||
def run(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Directory(py.test.collect.Directory):
|
|
||||||
def filefilter(self, fspath):
|
|
||||||
return fspath.check(basestarts='check_', ext='.txt')
|
|
||||||
def join(self, name):
|
|
||||||
if not name.endswith('.txt'):
|
|
||||||
return super(Directory, self).join(name)
|
|
||||||
p = self.fspath.join(name)
|
|
||||||
if p.check(file=1):
|
|
||||||
return CustomItem(p, parent=self)
|
|
||||||
""")
|
|
||||||
checkfile = o.ensure('somedir', 'moredir', 'check_something.txt')
|
|
||||||
return checkfile
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ class InlineCollection(FileCreation):
|
||||||
|
|
||||||
def getmodulecol(self, source, configargs=(), withsession=False):
|
def getmodulecol(self, source, configargs=(), withsession=False):
|
||||||
self.tmpdir.ensure("__init__.py")
|
self.tmpdir.ensure("__init__.py")
|
||||||
kw = {self.tmpdir.basename: py.code.Source(source).strip()}
|
kw = {"test_" + self.tmpdir.basename: py.code.Source(source).strip()}
|
||||||
path = self.makepyfile(**kw)
|
path = self.makepyfile(**kw)
|
||||||
self.config = self.parseconfig(path, *configargs)
|
self.config = self.parseconfig(path, *configargs)
|
||||||
if withsession:
|
if withsession:
|
||||||
|
@ -204,7 +204,7 @@ class InlineCollection(FileCreation):
|
||||||
|
|
||||||
def getitems(self, source):
|
def getitems(self, source):
|
||||||
modulecol = self.getmodulecol(source)
|
modulecol = self.getmodulecol(source)
|
||||||
return [modulecol.join(x) for x in modulecol.listdir()]
|
return modulecol.collect()
|
||||||
|
|
||||||
def getitem(self, source, funcname="test_func"):
|
def getitem(self, source, funcname="test_func"):
|
||||||
modulecol = self.getmodulecol(source)
|
modulecol = self.getmodulecol(source)
|
||||||
|
|
|
@ -22,79 +22,9 @@ def setup_module(mod):
|
||||||
mod.dummyconfig = DummyConfig()
|
mod.dummyconfig = DummyConfig()
|
||||||
|
|
||||||
def test_collect_versus_item():
|
def test_collect_versus_item():
|
||||||
path = setupdata.getexamplefile("filetest.py")
|
from py.__.test.collect import Collector, Item
|
||||||
col = py.test.collect.Module(path, config=dummyconfig)
|
assert not issubclass(Collector, Item)
|
||||||
assert not isinstance(col, py.test.collect.Item)
|
assert not issubclass(Item, Collector)
|
||||||
item = col.join("test_one")
|
|
||||||
assert not hasattr(item, "join")
|
|
||||||
assert not isinstance(item, py.test.collect.Collector)
|
|
||||||
|
|
||||||
def test_collector_deprecated_run_method():
|
|
||||||
path = setupdata.getexamplefile("filetest.py")
|
|
||||||
col = py.test.collect.Module(path, config=dummyconfig)
|
|
||||||
res1 = py.test.deprecated_call(col.run)
|
|
||||||
res2 = col.listdir()
|
|
||||||
assert res1 == res2
|
|
||||||
|
|
||||||
def test_module_assertion_setup():
|
|
||||||
path = setupdata.getexamplefile("filetest.py")
|
|
||||||
col = py.test.collect.Module(path, config=dummyconfig)
|
|
||||||
from py.__.magic import assertion
|
|
||||||
l = []
|
|
||||||
py.magic.patch(assertion, "invoke", lambda: l.append(None))
|
|
||||||
try:
|
|
||||||
col.setup()
|
|
||||||
finally:
|
|
||||||
py.magic.revert(assertion, "invoke")
|
|
||||||
x = l.pop()
|
|
||||||
assert x is None
|
|
||||||
py.magic.patch(assertion, "revoke", lambda: l.append(None))
|
|
||||||
try:
|
|
||||||
col.teardown()
|
|
||||||
finally:
|
|
||||||
py.magic.revert(assertion, "revoke")
|
|
||||||
x = l.pop()
|
|
||||||
assert x is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_failing_import_execfile():
|
|
||||||
dest = setupdata.getexamplefile('failingimport.py')
|
|
||||||
col = py.test.collect.Module(dest, config=dummyconfig)
|
|
||||||
py.test.raises(ImportError, col.listdir)
|
|
||||||
py.test.raises(ImportError, col.listdir)
|
|
||||||
|
|
||||||
def test_collect_listnames_and_back():
|
|
||||||
path = setupdata.getexamplefile("filetest.py")
|
|
||||||
col1 = py.test.collect.Directory(path.dirpath().dirpath(),
|
|
||||||
config=dummyconfig)
|
|
||||||
col2 = col1.join(path.dirpath().basename)
|
|
||||||
col3 = col2.join(path.basename)
|
|
||||||
l = col3.listnames()
|
|
||||||
assert len(l) == 3
|
|
||||||
x = col1._getitembynames(l[1:])
|
|
||||||
assert x.name == "filetest.py"
|
|
||||||
l2 = x.listnames()
|
|
||||||
assert len(l2) == 3
|
|
||||||
|
|
||||||
def test_finds_tests():
|
|
||||||
fn = setupdata.getexamplefile('filetest.py')
|
|
||||||
col = py.test.collect.Module(fn, config=dummyconfig)
|
|
||||||
l = col.listdir()
|
|
||||||
assert len(l) == 2
|
|
||||||
assert l[0] == 'test_one'
|
|
||||||
assert l[1] == 'TestClass'
|
|
||||||
|
|
||||||
def test_found_certain_testfiles():
|
|
||||||
tmp = py.test.ensuretemp("found_certain_testfiles")
|
|
||||||
tmp.ensure('test_found.py')
|
|
||||||
tmp.ensure('found_test.py')
|
|
||||||
|
|
||||||
col = py.test.collect.Directory(tmp, config=dummyconfig)
|
|
||||||
items = [col.join(x) for x in col.listdir()]
|
|
||||||
|
|
||||||
assert len(items) == 2
|
|
||||||
assert items[1].name == 'test_found.py'
|
|
||||||
assert items[0].name == 'found_test.py'
|
|
||||||
|
|
||||||
def test_ignored_certain_directories():
|
def test_ignored_certain_directories():
|
||||||
tmp = py.test.ensuretemp("ignore_certain_directories")
|
tmp = py.test.ensuretemp("ignore_certain_directories")
|
||||||
|
@ -107,80 +37,248 @@ def test_ignored_certain_directories():
|
||||||
tmp.ensure('test_found.py')
|
tmp.ensure('test_found.py')
|
||||||
|
|
||||||
col = py.test.collect.Directory(tmp, config=dummyconfig)
|
col = py.test.collect.Directory(tmp, config=dummyconfig)
|
||||||
items = col.listdir()
|
items = col.collect()
|
||||||
|
names = [x.name for x in items]
|
||||||
assert len(items) == 2
|
assert len(items) == 2
|
||||||
assert 'normal' in items
|
assert 'normal' in names
|
||||||
assert 'test_found.py' in items
|
assert 'test_found.py' in names
|
||||||
|
|
||||||
|
class TestCollect(suptest.InlineCollection):
|
||||||
|
def test_failing_import(self):
|
||||||
|
modcol = self.getmodulecol("import alksdjalskdjalkjals")
|
||||||
|
py.test.raises(ImportError, modcol.collect)
|
||||||
|
py.test.raises(ImportError, modcol.collect)
|
||||||
|
py.test.raises(ImportError, modcol.run)
|
||||||
|
|
||||||
|
def test_syntax_error_in_module(self):
|
||||||
|
modcol = self.getmodulecol("this is a syntax error")
|
||||||
|
py.test.raises(SyntaxError, modcol.collect)
|
||||||
|
py.test.raises(SyntaxError, modcol.collect)
|
||||||
|
py.test.raises(SyntaxError, modcol.run)
|
||||||
|
|
||||||
|
def test_listnames_and__getitembynames(self):
|
||||||
|
modcol = self.getmodulecol("pass")
|
||||||
|
names = modcol.listnames()
|
||||||
|
dircol = py.test.collect.Directory(modcol._config.topdir, config=modcol._config)
|
||||||
|
x = dircol._getitembynames(names)
|
||||||
|
assert modcol.name == x.name
|
||||||
|
assert modcol.name == x.name
|
||||||
|
|
||||||
|
def test_found_certain_testfiles(self):
|
||||||
|
p1 = self.makepyfile(test_found = "pass", found_test="pass")
|
||||||
|
col = py.test.collect.Directory(p1.dirpath(), config=dummyconfig)
|
||||||
|
items = col.collect()
|
||||||
|
assert len(items) == 2
|
||||||
|
assert items[1].name == 'test_found.py'
|
||||||
|
assert items[0].name == 'found_test.py'
|
||||||
|
|
||||||
|
def test_disabled_class(self):
|
||||||
|
modcol = self.getmodulecol("""
|
||||||
|
class TestClass:
|
||||||
|
disabled = True
|
||||||
|
def test_method(self):
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
l = modcol.collect()
|
||||||
|
assert len(l) == 1
|
||||||
|
modcol = l[0]
|
||||||
|
assert isinstance(modcol, py.test.collect.Class)
|
||||||
|
assert not modcol.collect()
|
||||||
|
|
||||||
|
def test_disabled_module(self):
|
||||||
|
modcol = self.getmodulecol("""
|
||||||
|
disabled = True
|
||||||
|
def setup_module(mod):
|
||||||
|
raise ValueError
|
||||||
|
""")
|
||||||
|
assert not modcol.collect()
|
||||||
|
assert not modcol.run()
|
||||||
|
|
||||||
|
def test_generative_functions(self):
|
||||||
|
modcol = self.getmodulecol("""
|
||||||
|
def func1(arg, arg2):
|
||||||
|
assert arg == arg2
|
||||||
|
|
||||||
|
def test_gen():
|
||||||
|
yield func1, 17, 3*5
|
||||||
|
yield func1, 42, 6*7
|
||||||
|
""")
|
||||||
|
colitems = modcol.collect()
|
||||||
|
assert len(colitems) == 1
|
||||||
|
gencol = colitems[0]
|
||||||
|
assert isinstance(gencol, py.test.collect.Generator)
|
||||||
|
gencolitems = gencol.collect()
|
||||||
|
assert len(gencolitems) == 2
|
||||||
|
assert isinstance(gencolitems[0], py.test.collect.Function)
|
||||||
|
assert isinstance(gencolitems[1], py.test.collect.Function)
|
||||||
|
assert gencolitems[0].name == '[0]'
|
||||||
|
assert gencolitems[0].obj.func_name == 'func1'
|
||||||
|
|
||||||
|
def test_generative_methods(self):
|
||||||
|
modcol = self.getmodulecol("""
|
||||||
|
def func1(arg, arg2):
|
||||||
|
assert arg == arg2
|
||||||
|
class TestGenMethods:
|
||||||
|
def test_gen(self):
|
||||||
|
yield func1, 17, 3*5
|
||||||
|
yield func1, 42, 6*7
|
||||||
|
""")
|
||||||
|
gencol = modcol.collect()[0].collect()[0].collect()[0]
|
||||||
|
assert isinstance(gencol, py.test.collect.Generator)
|
||||||
|
gencolitems = gencol.collect()
|
||||||
|
assert len(gencolitems) == 2
|
||||||
|
assert isinstance(gencolitems[0], py.test.collect.Function)
|
||||||
|
assert isinstance(gencolitems[1], py.test.collect.Function)
|
||||||
|
assert gencolitems[0].name == '[0]'
|
||||||
|
assert gencolitems[0].obj.func_name == 'func1'
|
||||||
|
|
||||||
|
def test_module_assertion_setup(self):
|
||||||
|
modcol = self.getmodulecol("pass")
|
||||||
|
from py.__.magic import assertion
|
||||||
|
l = []
|
||||||
|
py.magic.patch(assertion, "invoke", lambda: l.append(None))
|
||||||
|
try:
|
||||||
|
modcol.setup()
|
||||||
|
finally:
|
||||||
|
py.magic.revert(assertion, "invoke")
|
||||||
|
x = l.pop()
|
||||||
|
assert x is None
|
||||||
|
py.magic.patch(assertion, "revoke", lambda: l.append(None))
|
||||||
|
try:
|
||||||
|
modcol.teardown()
|
||||||
|
finally:
|
||||||
|
py.magic.revert(assertion, "revoke")
|
||||||
|
x = l.pop()
|
||||||
|
assert x is None
|
||||||
|
|
||||||
|
def test_check_equality_and_cmp_basic(self):
|
||||||
|
modcol = self.getmodulecol("""
|
||||||
|
def test_pass(): pass
|
||||||
|
def test_fail(): assert 0
|
||||||
|
""")
|
||||||
|
fn1 = modcol.join("test_pass")
|
||||||
|
assert isinstance(fn1, py.test.collect.Function)
|
||||||
|
fn2 = modcol.join("test_pass")
|
||||||
|
assert isinstance(fn2, py.test.collect.Function)
|
||||||
|
|
||||||
|
assert fn1 == fn2
|
||||||
|
assert fn1 != modcol
|
||||||
|
assert cmp(fn1, fn2) == 0
|
||||||
|
assert hash(fn1) == hash(fn2)
|
||||||
|
|
||||||
|
fn3 = modcol.join("test_fail")
|
||||||
|
assert isinstance(fn3, py.test.collect.Function)
|
||||||
|
assert not (fn1 == fn3)
|
||||||
|
assert fn1 != fn3
|
||||||
|
assert cmp(fn1, fn3) == -1
|
||||||
|
|
||||||
|
assert cmp(fn1, 10) == -1
|
||||||
|
assert cmp(fn2, 10) == -1
|
||||||
|
assert cmp(fn3, 10) == -1
|
||||||
|
for fn in fn1,fn2,fn3:
|
||||||
|
assert fn != 3
|
||||||
|
assert fn != modcol
|
||||||
|
assert fn != [1,2,3]
|
||||||
|
assert [1,2,3] != fn
|
||||||
|
assert modcol != fn
|
||||||
|
|
||||||
|
def test_directory_file_sorting(self):
|
||||||
|
p1 = self.makepyfile(test_one="hello")
|
||||||
|
p1.dirpath().mkdir("x")
|
||||||
|
p1.dirpath().mkdir("dir1")
|
||||||
|
self.makepyfile(test_two="hello")
|
||||||
|
p1.dirpath().mkdir("dir2")
|
||||||
|
config = self.parseconfig()
|
||||||
|
col = config.getfsnode(p1.dirpath())
|
||||||
|
names = [x.name for x in col.collect()]
|
||||||
|
assert names == ["dir1", "dir2", "test_one.py", "test_two.py", "x"]
|
||||||
|
|
||||||
|
def test_collector_deprecated_run_method(self):
|
||||||
|
modcol = self.getmodulecol("pass")
|
||||||
|
res1 = py.test.deprecated_call(modcol.run)
|
||||||
|
res2 = modcol.collect()
|
||||||
|
assert res1 == [x.name for x in res2]
|
||||||
|
|
||||||
|
class TestCustomConftests(suptest.InlineCollection):
|
||||||
|
def test_extra_python_files_and_functions(self):
|
||||||
|
self.makepyfile(conftest="""
|
||||||
|
import py
|
||||||
|
class MyFunction(py.test.collect.Function):
|
||||||
|
pass
|
||||||
|
class Directory(py.test.collect.Directory):
|
||||||
|
def consider_file(self, path, usefilters=True):
|
||||||
|
if path.check(fnmatch="check_*.py"):
|
||||||
|
return self.Module(path, parent=self)
|
||||||
|
return super(Directory, self).consider_file(path, usefilters=usefilters)
|
||||||
|
class myfuncmixin:
|
||||||
|
Function = MyFunction
|
||||||
|
def funcnamefilter(self, name):
|
||||||
|
return name.startswith('check_')
|
||||||
|
class Module(myfuncmixin, py.test.collect.Module):
|
||||||
|
def classnamefilter(self, name):
|
||||||
|
return name.startswith('CustomTestClass')
|
||||||
|
class Instance(myfuncmixin, py.test.collect.Instance):
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
checkfile = self.makepyfile(check_file="""
|
||||||
|
def check_func():
|
||||||
|
assert 42 == 42
|
||||||
|
class CustomTestClass:
|
||||||
|
def check_method(self):
|
||||||
|
assert 23 == 23
|
||||||
|
""")
|
||||||
|
# check that directory collects "check_" files
|
||||||
|
config = self.parseconfig()
|
||||||
|
col = config.getfsnode(checkfile.dirpath())
|
||||||
|
colitems = col.collect()
|
||||||
|
assert len(colitems) == 1
|
||||||
|
assert isinstance(colitems[0], py.test.collect.Module)
|
||||||
|
|
||||||
|
# check that module collects "check_" functions and methods
|
||||||
|
config = self.parseconfig(checkfile)
|
||||||
|
col = config.getfsnode(checkfile)
|
||||||
|
assert isinstance(col, py.test.collect.Module)
|
||||||
|
colitems = col.collect()
|
||||||
|
assert len(colitems) == 2
|
||||||
|
funccol = colitems[0]
|
||||||
|
assert isinstance(funccol, py.test.collect.Function)
|
||||||
|
assert funccol.name == "check_func"
|
||||||
|
clscol = colitems[1]
|
||||||
|
assert isinstance(clscol, py.test.collect.Class)
|
||||||
|
colitems = clscol.collect()[0].collect()
|
||||||
|
assert len(colitems) == 1
|
||||||
|
assert colitems[0].name == "check_method"
|
||||||
|
|
||||||
|
def test_non_python_files(self):
|
||||||
|
self.makepyfile(conftest="""
|
||||||
|
import py
|
||||||
|
class CustomItem(py.test.collect.Item):
|
||||||
|
def run(self):
|
||||||
|
pass
|
||||||
|
class Directory(py.test.collect.Directory):
|
||||||
|
def consider_file(self, fspath, usefilters=True):
|
||||||
|
if fspath.ext == ".xxx":
|
||||||
|
return CustomItem(fspath.basename, parent=self)
|
||||||
|
""")
|
||||||
|
checkfile = self._makefile(ext="xxx", hello="world")
|
||||||
|
self.makepyfile(x="")
|
||||||
|
self.maketxtfile(x="")
|
||||||
|
config = self.parseconfig()
|
||||||
|
dircol = config.getfsnode(checkfile.dirpath())
|
||||||
|
colitems = dircol.collect()
|
||||||
|
assert len(colitems) == 1
|
||||||
|
assert colitems[0].name == "hello.xxx"
|
||||||
|
assert colitems[0].__class__.__name__ == "CustomItem"
|
||||||
|
|
||||||
|
item = config.getfsnode(checkfile)
|
||||||
|
assert item.name == "hello.xxx"
|
||||||
|
assert item.__class__.__name__ == "CustomItem"
|
||||||
|
|
||||||
def test_failing_import_directory():
|
|
||||||
class MyDirectory(py.test.collect.Directory):
|
|
||||||
def filefilter(self, p):
|
|
||||||
return p.check(fnmatch='testspecial*.py')
|
|
||||||
filetest = setupdata.getexamplefile("testspecial_importerror.py")
|
|
||||||
mydir = MyDirectory(filetest.dirpath(), config=dummyconfig)
|
|
||||||
l = mydir.listdir()
|
|
||||||
assert len(l) == 1
|
|
||||||
col = mydir.join(l[0])
|
|
||||||
assert isinstance(col, py.test.collect.Module)
|
|
||||||
py.test.raises(ImportError, col.listdir)
|
|
||||||
|
|
||||||
def test_module_file_not_found():
|
def test_module_file_not_found():
|
||||||
fn = tmpdir.join('nada','no')
|
fn = tmpdir.join('nada','no')
|
||||||
col = py.test.collect.Module(fn, config=dummyconfig)
|
col = py.test.collect.Module(fn, config=dummyconfig)
|
||||||
py.test.raises(py.error.ENOENT, col.listdir)
|
py.test.raises(py.error.ENOENT, col.collect)
|
||||||
|
|
||||||
def test_syntax_error_in_module():
|
|
||||||
modpath = setupdata.getexamplefile("syntax_error.py")
|
|
||||||
col = py.test.collect.Module(modpath, config=dummyconfig)
|
|
||||||
py.test.raises(SyntaxError, col.listdir)
|
|
||||||
|
|
||||||
def test_disabled_class():
|
|
||||||
p = setupdata.getexamplefile('disabled.py')
|
|
||||||
col = py.test.collect.Module(p, config=dummyconfig)
|
|
||||||
l = col.listdir()
|
|
||||||
assert len(l) == 1
|
|
||||||
col = col.join(l[0])
|
|
||||||
assert isinstance(col, py.test.collect.Class)
|
|
||||||
assert not col.listdir()
|
|
||||||
|
|
||||||
def test_disabled_module():
|
|
||||||
p = setupdata.getexamplefile("disabled_module.py")
|
|
||||||
col = py.test.collect.Module(p, config=dummyconfig)
|
|
||||||
l = col.listdir()
|
|
||||||
assert len(l) == 0
|
|
||||||
|
|
||||||
def test_generative_simple():
|
|
||||||
tfile = setupdata.getexamplefile('test_generative.py')
|
|
||||||
col = py.test.collect.Module(tfile, config=dummyconfig)
|
|
||||||
l = col.listdir()
|
|
||||||
assert len(l) == 2
|
|
||||||
l = col.multijoin(l)
|
|
||||||
|
|
||||||
generator = l[0]
|
|
||||||
assert isinstance(generator, py.test.collect.Generator)
|
|
||||||
l2 = generator.listdir()
|
|
||||||
assert len(l2) == 2
|
|
||||||
l2 = generator.multijoin(l2)
|
|
||||||
assert isinstance(l2[0], py.test.collect.Function)
|
|
||||||
assert isinstance(l2[1], py.test.collect.Function)
|
|
||||||
assert l2[0].name == '[0]'
|
|
||||||
assert l2[1].name == '[1]'
|
|
||||||
|
|
||||||
assert l2[0].obj.func_name == 'func1'
|
|
||||||
|
|
||||||
classlist = l[1].listdir()
|
|
||||||
assert len(classlist) == 1
|
|
||||||
classlist = l[1].multijoin(classlist)
|
|
||||||
cls = classlist[0]
|
|
||||||
generator = cls.join(cls.listdir()[0])
|
|
||||||
assert isinstance(generator, py.test.collect.Generator)
|
|
||||||
l2 = generator.listdir()
|
|
||||||
assert len(l2) == 2
|
|
||||||
l2 = generator.multijoin(l2)
|
|
||||||
assert isinstance(l2[0], py.test.collect.Function)
|
|
||||||
assert isinstance(l2[1], py.test.collect.Function)
|
|
||||||
assert l2[0].name == '[0]'
|
|
||||||
assert l2[1].name == '[1]'
|
|
||||||
|
|
||||||
|
|
||||||
def test_order_of_execution_generator_same_codeline():
|
def test_order_of_execution_generator_same_codeline():
|
||||||
|
@ -238,52 +336,6 @@ def test_order_of_execution_generator_different_codeline():
|
||||||
assert passed == 4
|
assert passed == 4
|
||||||
assert not skipped and not failed
|
assert not skipped and not failed
|
||||||
|
|
||||||
def test_check_directory_ordered():
|
|
||||||
tmpdir = py.test.ensuretemp("test_check_directory_ordered")
|
|
||||||
fnames = []
|
|
||||||
for i in range(9, -1, -1):
|
|
||||||
x = tmpdir.ensure("xdir%d" %(i, ), dir=1)
|
|
||||||
fnames.append(x.basename)
|
|
||||||
for i in range(9, -1, -1):
|
|
||||||
x = tmpdir.ensure("test_file%d.py" % (i,))
|
|
||||||
fnames.append(x.basename)
|
|
||||||
fnames.sort()
|
|
||||||
tmpdir.ensure('adir', dir=1)
|
|
||||||
fnames.insert(10, 'adir')
|
|
||||||
col = py.test.collect.Directory(tmpdir, config=dummyconfig)
|
|
||||||
names = col.listdir()
|
|
||||||
assert names == fnames
|
|
||||||
|
|
||||||
def test_check_equality_and_cmp_basic():
|
|
||||||
path = setupdata.getexamplefile("funcexamples.py")
|
|
||||||
col = py.test.collect.Module(path, config=dummyconfig)
|
|
||||||
fn1 = col.join("funcpassed")
|
|
||||||
assert isinstance(fn1, py.test.collect.Function)
|
|
||||||
fn2 = col.join("funcpassed")
|
|
||||||
assert isinstance(fn2, py.test.collect.Function)
|
|
||||||
|
|
||||||
assert fn1 == fn2
|
|
||||||
assert fn1 != col
|
|
||||||
assert cmp(fn1, fn2) == 0
|
|
||||||
assert hash(fn1) == hash(fn2)
|
|
||||||
|
|
||||||
fn3 = col.join("funcfailed")
|
|
||||||
assert isinstance(fn3, py.test.collect.Function)
|
|
||||||
assert not (fn1 == fn3)
|
|
||||||
assert fn1 != fn3
|
|
||||||
assert cmp(fn1, fn3) == -1
|
|
||||||
|
|
||||||
assert cmp(fn1, 10) == -1
|
|
||||||
assert cmp(fn2, 10) == -1
|
|
||||||
assert cmp(fn3, 10) == -1
|
|
||||||
for fn in fn1,fn2,fn3:
|
|
||||||
assert fn != 3
|
|
||||||
assert fn != col
|
|
||||||
assert fn != [1,2,3]
|
|
||||||
assert [1,2,3] != fn
|
|
||||||
assert col != fn
|
|
||||||
|
|
||||||
|
|
||||||
def test_function_equality():
|
def test_function_equality():
|
||||||
config = py.test.config._reparse([tmpdir])
|
config = py.test.config._reparse([tmpdir])
|
||||||
f1 = py.test.collect.Function(name="name", config=config,
|
f1 = py.test.collect.Function(name="name", config=config,
|
||||||
|
@ -341,22 +393,6 @@ class Testgenitems:
|
||||||
assert hash(i) != hash(j)
|
assert hash(i) != hash(j)
|
||||||
assert i != j
|
assert i != j
|
||||||
|
|
||||||
def test_skip_by_conftest_directory(self):
|
|
||||||
from py.__.test import outcome
|
|
||||||
self.tmp.ensure("subdir", "conftest.py").write(py.code.Source("""
|
|
||||||
import py
|
|
||||||
class Directory(py.test.collect.Directory):
|
|
||||||
def listdir(self):
|
|
||||||
py.test.skip("intentional")
|
|
||||||
"""))
|
|
||||||
items, events = self._genitems()
|
|
||||||
assert len(items) == 0
|
|
||||||
skips = [x for x in events
|
|
||||||
if isinstance(x, event.CollectionReport)
|
|
||||||
and x.colitem.name == 'subdir']
|
|
||||||
assert len(skips) == 1
|
|
||||||
assert skips[0].skipped
|
|
||||||
|
|
||||||
def test_root_conftest_syntax_error(self):
|
def test_root_conftest_syntax_error(self):
|
||||||
# do we want to unify behaviour with
|
# do we want to unify behaviour with
|
||||||
# test_subdir_conftest_error?
|
# test_subdir_conftest_error?
|
||||||
|
@ -407,57 +443,6 @@ class Testgenitems:
|
||||||
assert items[1].name == 'test_method_one'
|
assert items[1].name == 'test_method_one'
|
||||||
assert items[2].name == 'test_method_one'
|
assert items[2].name == 'test_method_one'
|
||||||
|
|
||||||
def test_custom_python_collection_from_conftest(self):
|
|
||||||
checkfile = setupdata.setup_customconfigtest(self.tmp)
|
|
||||||
for x in (self.tmp, checkfile, checkfile.dirpath()):
|
|
||||||
items, events = self._genitems(x)
|
|
||||||
assert len(items) == 2
|
|
||||||
#assert items[1].__class__.__name__ == 'MyFunction'
|
|
||||||
|
|
||||||
return None # XXX shift below to session test?
|
|
||||||
# test that running a session works from the directories
|
|
||||||
old = o.chdir()
|
|
||||||
try:
|
|
||||||
sorter = suptest.events_from_cmdline([])
|
|
||||||
passed, skipped, failed = sorter.countoutcomes()
|
|
||||||
assert passed == 2
|
|
||||||
assert skipped == failed == 0
|
|
||||||
finally:
|
|
||||||
old.chdir()
|
|
||||||
|
|
||||||
# test that running the file directly works
|
|
||||||
sorter = suptest.events_from_cmdline([str(checkfile)])
|
|
||||||
passed, skipped, failed = sorter.countoutcomes()
|
|
||||||
assert passed == 2
|
|
||||||
assert skipped == failed == 0
|
|
||||||
|
|
||||||
def test_custom_NONpython_collection_from_conftest(self):
|
|
||||||
checkfile = setupdata.setup_non_python_dir(self.tmp)
|
|
||||||
|
|
||||||
for x in (self.tmp, checkfile, checkfile.dirpath()):
|
|
||||||
print "checking that %s returns custom items" % (x,)
|
|
||||||
items, events = self._genitems(x)
|
|
||||||
assert len(items) == 1
|
|
||||||
assert items[0].__class__.__name__ == 'CustomItem'
|
|
||||||
|
|
||||||
return None # XXX shift below to session tests?
|
|
||||||
|
|
||||||
# test that running a session works from the directories
|
|
||||||
old = self.tmp.chdir()
|
|
||||||
try:
|
|
||||||
sorter = suptest.events_from_cmdline([])
|
|
||||||
passed, skipped, failed = sorter.countoutcomes()
|
|
||||||
assert passed == 1
|
|
||||||
assert skipped == failed == 0
|
|
||||||
finally:
|
|
||||||
old.chdir()
|
|
||||||
|
|
||||||
# test that running the file directly works
|
|
||||||
sorter = suptest.events_from_cmdline([str(checkfile)])
|
|
||||||
passed, skipped, failed = sorter.countoutcomes()
|
|
||||||
assert passed == 1
|
|
||||||
assert skipped == failed == 0
|
|
||||||
|
|
||||||
def test_collect_doctest_files_with_test_prefix(self):
|
def test_collect_doctest_files_with_test_prefix(self):
|
||||||
self.tmp.ensure("whatever.txt")
|
self.tmp.ensure("whatever.txt")
|
||||||
checkfile = self.tmp.ensure("test_something.txt")
|
checkfile = self.tmp.ensure("test_something.txt")
|
||||||
|
@ -548,7 +533,7 @@ class TestCollectorReprs(suptest.InlineCollection):
|
||||||
assert info.lineno == 1
|
assert info.lineno == 1
|
||||||
assert info.modpath == "test_gen"
|
assert info.modpath == "test_gen"
|
||||||
|
|
||||||
genitem = gencol.join(gencol.listdir()[0])
|
genitem = gencol.collect()[0]
|
||||||
info = genitem.repr_metainfo()
|
info = genitem.repr_metainfo()
|
||||||
assert info.fspath == modcol.fspath
|
assert info.fspath == modcol.fspath
|
||||||
assert info.lineno == 2
|
assert info.lineno == 2
|
||||||
|
|
|
@ -74,32 +74,6 @@ def test_config_getvalue_honours_conftest():
|
||||||
py.test.raises(KeyError, 'config.getvalue("y", o)')
|
py.test.raises(KeyError, 'config.getvalue("y", o)')
|
||||||
|
|
||||||
|
|
||||||
def test_siblingconftest_fails_maybe():
|
|
||||||
from py.__.test import config
|
|
||||||
cfg = config.Config()
|
|
||||||
o = py.test.ensuretemp('siblingconftest')
|
|
||||||
o.ensure("__init__.py")
|
|
||||||
o.ensure("sister1", "__init__.py")
|
|
||||||
o.ensure("sister1", "conftest.py").write(py.code.Source("""
|
|
||||||
x = 2
|
|
||||||
"""))
|
|
||||||
|
|
||||||
o.ensure("sister2", "__init__.py")
|
|
||||||
o.ensure("sister2", "conftest.py").write(py.code.Source("""
|
|
||||||
raise SyntaxError
|
|
||||||
"""))
|
|
||||||
|
|
||||||
assert cfg.getvalue(path=o.join('sister1'), name='x') == 2
|
|
||||||
old = o.chdir()
|
|
||||||
try:
|
|
||||||
pytestpath = py.magic.autopath().dirpath().dirpath().dirpath().join(
|
|
||||||
'bin/py.test')
|
|
||||||
print py.process.cmdexec('python "%s" sister1' % (pytestpath,))
|
|
||||||
o.join('sister1').chdir()
|
|
||||||
print py.process.cmdexec('python "%s"' % (pytestpath,))
|
|
||||||
finally:
|
|
||||||
old.chdir()
|
|
||||||
|
|
||||||
def test_config_overwrite():
|
def test_config_overwrite():
|
||||||
o = py.test.ensuretemp('testconfigget')
|
o = py.test.ensuretemp('testconfigget')
|
||||||
o.ensure("conftest.py").write("x=1")
|
o.ensure("conftest.py").write("x=1")
|
||||||
|
@ -338,7 +312,7 @@ class TestSessionAndOptions:
|
||||||
def test_conflict_options(self):
|
def test_conflict_options(self):
|
||||||
def check_conflict_option(opts):
|
def check_conflict_option(opts):
|
||||||
print "testing if options conflict:", " ".join(opts)
|
print "testing if options conflict:", " ".join(opts)
|
||||||
path = setupdata.getexamplefile("filetest.py")
|
path = setupdata.getexamplefile("file_test.py")
|
||||||
config = py.test.config._reparse(opts + [path])
|
config = py.test.config._reparse(opts + [path])
|
||||||
py.test.raises((ValueError, SystemExit), """
|
py.test.raises((ValueError, SystemExit), """
|
||||||
config.initsession()
|
config.initsession()
|
||||||
|
@ -355,7 +329,7 @@ class TestSessionAndOptions:
|
||||||
|
|
||||||
def test_implied_options(self):
|
def test_implied_options(self):
|
||||||
def check_implied_option(opts, expr):
|
def check_implied_option(opts, expr):
|
||||||
path = setupdata.getexamplefile("filetest.py")
|
path = setupdata.getexamplefile("file_test.py")
|
||||||
config = py.test.config._reparse(opts + [path])
|
config = py.test.config._reparse(opts + [path])
|
||||||
session = config.initsession()
|
session = config.initsession()
|
||||||
assert eval(expr, session.config.option.__dict__)
|
assert eval(expr, session.config.option.__dict__)
|
||||||
|
@ -374,14 +348,14 @@ class TestSessionAndOptions:
|
||||||
passed, skipped, failed = sorter.countoutcomes()
|
passed, skipped, failed = sorter.countoutcomes()
|
||||||
assert failed == 2
|
assert failed == 2
|
||||||
assert skipped == passed == 0
|
assert skipped == passed == 0
|
||||||
path = setupdata.getexamplefile("filetest.py")
|
path = setupdata.getexamplefile("file_test.py")
|
||||||
for opts in ([], ['-l'], ['-s'], ['--tb=no'], ['--tb=short'],
|
for opts in ([], ['-l'], ['-s'], ['--tb=no'], ['--tb=short'],
|
||||||
['--tb=long'], ['--fulltrace'], ['--nomagic'],
|
['--tb=long'], ['--fulltrace'], ['--nomagic'],
|
||||||
['--traceconfig'], ['-v'], ['-v', '-v']):
|
['--traceconfig'], ['-v'], ['-v', '-v']):
|
||||||
yield runfiletest, opts + [path]
|
yield runfiletest, opts + [path]
|
||||||
|
|
||||||
def test_is_not_boxed_by_default(self):
|
def test_is_not_boxed_by_default(self):
|
||||||
path = setupdata.getexamplefile("filetest.py")
|
path = setupdata.getexamplefile("file_test.py")
|
||||||
config = py.test.config._reparse([path])
|
config = py.test.config._reparse([path])
|
||||||
assert not config.option.boxed
|
assert not config.option.boxed
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
|
||||||
|
import py
|
||||||
|
from py.__.test.testing import suptest
|
||||||
|
|
||||||
|
class TestCollectDeprecated(suptest.InlineCollection):
|
||||||
|
def test_directory_run_join_warnings(self):
|
||||||
|
p = self.makepyfile(test_one="")
|
||||||
|
config = self.parseconfig()
|
||||||
|
dirnode = config.getfsnode(p.dirpath())
|
||||||
|
py.test.deprecated_call(dirnode.run)
|
||||||
|
# XXX for directories we still have join()
|
||||||
|
#py.test.deprecated_call(dirnode.join, 'test_one')
|
||||||
|
|
||||||
|
def test_collect_with_deprecated_run_and_join(self):
|
||||||
|
self.makepyfile(conftest="""
|
||||||
|
import py
|
||||||
|
|
||||||
|
class MyInstance(py.test.collect.Instance):
|
||||||
|
def run(self):
|
||||||
|
return ['check2']
|
||||||
|
def join(self, name):
|
||||||
|
if name == 'check2':
|
||||||
|
return self.Function(name=name, parent=self)
|
||||||
|
|
||||||
|
class MyClass(py.test.collect.Class):
|
||||||
|
def run(self):
|
||||||
|
return ['check2']
|
||||||
|
def join(self, name):
|
||||||
|
return MyInstance(name='i', parent=self)
|
||||||
|
|
||||||
|
class MyModule(py.test.collect.Module):
|
||||||
|
def run(self):
|
||||||
|
return ['check', 'Cls']
|
||||||
|
def join(self, name):
|
||||||
|
if name == 'check':
|
||||||
|
return self.Function(name, parent=self)
|
||||||
|
if name == 'Cls':
|
||||||
|
return MyClass(name, parent=self)
|
||||||
|
|
||||||
|
class MyDirectory(py.test.collect.Directory):
|
||||||
|
Module = MyModule
|
||||||
|
def run(self):
|
||||||
|
return ['somefile.py']
|
||||||
|
def join(self, name):
|
||||||
|
if name == "somefile.py":
|
||||||
|
return self.Module(self.fspath.join(name), parent=self)
|
||||||
|
Directory = MyDirectory
|
||||||
|
""")
|
||||||
|
p = self.makepyfile(somefile="""
|
||||||
|
def check(): pass
|
||||||
|
class Cls:
|
||||||
|
def check2(self): pass
|
||||||
|
""")
|
||||||
|
config = self.parseconfig()
|
||||||
|
dirnode = config.getfsnode(p.dirpath())
|
||||||
|
colitems = py.test.deprecated_call(dirnode.collect)
|
||||||
|
assert len(colitems) == 1
|
||||||
|
modcol = colitems[0]
|
||||||
|
assert modcol.name == "somefile.py"
|
||||||
|
colitems = py.test.deprecated_call(modcol.collect)
|
||||||
|
assert len(colitems) == 2
|
||||||
|
assert colitems[0].name == 'check'
|
||||||
|
assert colitems[1].name == 'Cls'
|
||||||
|
clscol = colitems[1]
|
||||||
|
colitems = py.test.deprecated_call(clscol.collect)
|
||||||
|
assert len(colitems) == 1
|
||||||
|
icol = colitems[0]
|
||||||
|
colitems = py.test.deprecated_call(icol.collect)
|
||||||
|
assert len(colitems) == 1
|
||||||
|
assert colitems[0].name == 'check2'
|
||||||
|
|
||||||
|
def test_collect_with_deprecated_join_but_no_run(self):
|
||||||
|
self.makepyfile(conftest="""
|
||||||
|
import py
|
||||||
|
|
||||||
|
class Module(py.test.collect.Module):
|
||||||
|
def funcnamefilter(self, name):
|
||||||
|
if name.startswith("check_"):
|
||||||
|
return True
|
||||||
|
return super(Module, self).funcnamefilter(name)
|
||||||
|
def join(self, name):
|
||||||
|
if name.startswith("check_"):
|
||||||
|
return self.Function(name, parent=self)
|
||||||
|
assert name != "SomeClass", "join should not be called with this name"
|
||||||
|
""")
|
||||||
|
col = self.getmodulecol("""
|
||||||
|
def somefunc(): pass
|
||||||
|
def check_one(): pass
|
||||||
|
class SomeClass: pass
|
||||||
|
""")
|
||||||
|
colitems = py.test.deprecated_call(col.collect)
|
||||||
|
assert len(colitems) == 1
|
||||||
|
funcitem = colitems[0]
|
||||||
|
assert funcitem.name == "check_one"
|
||||||
|
|
||||||
|
def test_function_custom_run(self):
|
||||||
|
self.makepyfile(conftest="""
|
||||||
|
import py
|
||||||
|
class MyFunction(py.test.collect.Function):
|
||||||
|
def run(self):
|
||||||
|
pass
|
||||||
|
Function=MyFunction
|
||||||
|
""")
|
||||||
|
modcol = self.getmodulecol("def test_func(): pass")
|
||||||
|
funcitem = modcol.collect()[0]
|
||||||
|
assert funcitem.name == 'test_func'
|
||||||
|
py.test.deprecated_call(funcitem.runtest)
|
||||||
|
|
||||||
|
def test_function_custom_execute(self):
|
||||||
|
self.makepyfile(conftest="""
|
||||||
|
import py
|
||||||
|
class MyFunction(py.test.collect.Function):
|
||||||
|
def execute(self, obj, *args):
|
||||||
|
pass
|
||||||
|
Function=MyFunction
|
||||||
|
""")
|
||||||
|
modcol = self.getmodulecol("def test_func(): pass")
|
||||||
|
funcitem = modcol.collect()[0]
|
||||||
|
assert funcitem.name == 'test_func'
|
||||||
|
py.test.deprecated_call(funcitem.runtest)
|
||||||
|
|
||||||
|
def test_function_deprecated_run_execute(self):
|
||||||
|
modcol = self.getmodulecol("def test_some(): pass")
|
||||||
|
funcitem = modcol.collect()[0]
|
||||||
|
py.test.deprecated_call(funcitem.run)
|
||||||
|
py.test.deprecated_call(funcitem.execute, funcitem.obj)
|
||||||
|
|
||||||
|
def test_function_deprecated_run_recursive(self):
|
||||||
|
self.makepyfile(conftest="""
|
||||||
|
import py
|
||||||
|
class Module(py.test.collect.Module):
|
||||||
|
def run(self):
|
||||||
|
return super(Module, self).run()
|
||||||
|
""")
|
||||||
|
modcol = self.getmodulecol("def test_some(): pass")
|
||||||
|
colitems = py.test.deprecated_call(modcol.collect)
|
||||||
|
funcitem = colitems[0]
|
|
@ -16,7 +16,7 @@ class TestDoctests(InlineCollection):
|
||||||
config = self.parseconfig(txtfile)
|
config = self.parseconfig(txtfile)
|
||||||
col = config.getfsnode(txtfile)
|
col = config.getfsnode(txtfile)
|
||||||
testitem = col.join(txtfile.basename)
|
testitem = col.join(txtfile.basename)
|
||||||
res = testitem.execute()
|
res = testitem.runtest()
|
||||||
assert res is None
|
assert res is None
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +29,6 @@ class TestDoctests(InlineCollection):
|
||||||
2
|
2
|
||||||
"""))
|
"""))
|
||||||
testitem = py.test.collect.DoctestFile(p).join(p.basename)
|
testitem = py.test.collect.DoctestFile(p).join(p.basename)
|
||||||
excinfo = py.test.raises(Failed, "testitem.execute()")
|
excinfo = py.test.raises(Failed, "testitem.runtest()")
|
||||||
repr = testitem.repr_failure(excinfo, ("", ""))
|
repr = testitem.repr_failure(excinfo, ("", ""))
|
||||||
assert repr.reprlocation
|
assert repr.reprlocation
|
||||||
|
|
|
@ -38,7 +38,7 @@ class TestEventBus:
|
||||||
|
|
||||||
class TestItemTestReport(object):
|
class TestItemTestReport(object):
|
||||||
def test_toterminal(self):
|
def test_toterminal(self):
|
||||||
sorter = suptest.events_run_example("filetest.py")
|
sorter = suptest.events_run_example("file_test.py")
|
||||||
reports = sorter.get(event.ItemTestReport)
|
reports = sorter.get(event.ItemTestReport)
|
||||||
ev = reports[0]
|
ev = reports[0]
|
||||||
assert ev.failed
|
assert ev.failed
|
||||||
|
@ -54,5 +54,5 @@ class TestItemTestReport(object):
|
||||||
##assert ev.repr_run.find("AssertionError") != -1
|
##assert ev.repr_run.find("AssertionError") != -1
|
||||||
filepath = ev.colitem.fspath
|
filepath = ev.colitem.fspath
|
||||||
#filepath , modpath = ev.itemrepr_path
|
#filepath , modpath = ev.itemrepr_path
|
||||||
assert str(filepath).endswith("filetest.py")
|
assert str(filepath).endswith("file_test.py")
|
||||||
#assert modpath.endswith("filetest.test_one")
|
#assert modpath.endswith("file_test.test_one")
|
||||||
|
|
|
@ -8,7 +8,7 @@ from py.__.code.testing.test_excinfo import TWMock
|
||||||
class TestItemTestReport(object):
|
class TestItemTestReport(object):
|
||||||
|
|
||||||
def test_toterminal(self):
|
def test_toterminal(self):
|
||||||
sorter = suptest.events_run_example("filetest.py")
|
sorter = suptest.events_run_example("file_test.py")
|
||||||
reports = sorter.get(event.ItemTestReport)
|
reports = sorter.get(event.ItemTestReport)
|
||||||
ev = reports[0]
|
ev = reports[0]
|
||||||
assert ev.failed
|
assert ev.failed
|
||||||
|
@ -24,7 +24,7 @@ class TestItemTestReport(object):
|
||||||
##assert ev.repr_run.find("AssertionError") != -1
|
##assert ev.repr_run.find("AssertionError") != -1
|
||||||
filepath = ev.colitem.fspath
|
filepath = ev.colitem.fspath
|
||||||
#filepath , modpath = ev.itemrepr_path
|
#filepath , modpath = ev.itemrepr_path
|
||||||
assert str(filepath).endswith("filetest.py")
|
assert str(filepath).endswith("file_test.py")
|
||||||
#assert modpath.endswith("filetest.test_one")
|
#assert modpath.endswith("file_test.test_one")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ def setup_module(mod):
|
||||||
class TestKeywordSelection:
|
class TestKeywordSelection:
|
||||||
def test_select_simple(self):
|
def test_select_simple(self):
|
||||||
def check(keyword, name):
|
def check(keyword, name):
|
||||||
sorter = suptest.events_run_example("filetest.py",
|
sorter = suptest.events_run_example("file_test.py",
|
||||||
'-s', '-k', keyword)
|
'-s', '-k', keyword)
|
||||||
passed, skipped, failed = sorter.listoutcomes()
|
passed, skipped, failed = sorter.listoutcomes()
|
||||||
assert len(failed) == 1
|
assert len(failed) == 1
|
||||||
|
@ -190,6 +190,21 @@ class SessionTests(suptest.InlineCollection):
|
||||||
assert (out.find("[unknown exception raised in repr()]") != -1 or
|
assert (out.find("[unknown exception raised in repr()]") != -1 or
|
||||||
out.find("TypeError") != -1)
|
out.find("TypeError") != -1)
|
||||||
|
|
||||||
|
def test_skip_by_conftest_directory(self):
|
||||||
|
from py.__.test import outcome
|
||||||
|
self.makepyfile(conftest="""
|
||||||
|
import py
|
||||||
|
class Directory(py.test.collect.Directory):
|
||||||
|
def collect(self):
|
||||||
|
py.test.skip("intentional")
|
||||||
|
""", test_file="""
|
||||||
|
def test_one(): pass
|
||||||
|
""")
|
||||||
|
sorter = self.events_from_cmdline()
|
||||||
|
skips = sorter.get(event.CollectionReport)
|
||||||
|
assert len(skips) == 1
|
||||||
|
assert skips[0].skipped
|
||||||
|
|
||||||
class TestNewSession(SessionTests):
|
class TestNewSession(SessionTests):
|
||||||
def test_pdb_run(self):
|
def test_pdb_run(self):
|
||||||
tfile = self.makepyfile(test_one="""
|
tfile = self.makepyfile(test_one="""
|
||||||
|
|
Loading…
Reference in New Issue