2008-08-16 23:26:59 +08:00
|
|
|
"""
|
|
|
|
Collect test items at filesystem and python module levels.
|
|
|
|
|
|
|
|
Collectors and test items form a tree. The difference
|
|
|
|
between a collector and a test item as seen from the session
|
|
|
|
is smalll. Collectors usually return a list of child
|
|
|
|
collectors/items whereas items usually return None
|
|
|
|
indicating a successful test run.
|
|
|
|
|
|
|
|
The is a schematic example of a tree of collectors and test items::
|
|
|
|
|
|
|
|
Directory
|
|
|
|
Directory
|
|
|
|
CustomCollector # provided via conftest's
|
|
|
|
CustomItem # provided via conftest's
|
|
|
|
CustomItem # provided via conftest's
|
|
|
|
Directory
|
|
|
|
...
|
|
|
|
|
|
|
|
"""
|
|
|
|
import py
|
2008-09-10 17:47:37 +08:00
|
|
|
from py.__.misc.warn import APIWARN
|
2009-03-19 03:23:38 +08:00
|
|
|
from py.__.test.outcome import Skipped
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
def configproperty(name):
|
|
|
|
def fget(self):
|
|
|
|
#print "retrieving %r property from %s" %(name, self.fspath)
|
2009-03-18 07:48:07 +08:00
|
|
|
return self.config.getvalue(name, self.fspath)
|
2008-08-16 23:26:59 +08:00
|
|
|
return property(fget)
|
|
|
|
|
|
|
|
class ReprMetaInfo(object):
|
|
|
|
def __init__(self, fspath=None, lineno=None, modpath=None):
|
|
|
|
self.fspath = fspath
|
|
|
|
self.lineno = lineno
|
|
|
|
self.modpath = modpath
|
|
|
|
|
|
|
|
def verboseline(self, basedir=None):
|
|
|
|
params = self.__dict__.copy()
|
|
|
|
if self.fspath:
|
|
|
|
if basedir is not None:
|
2009-02-27 18:18:27 +08:00
|
|
|
params['fspath'] = basedir.bestrelpath(self.fspath)
|
2008-08-16 23:26:59 +08:00
|
|
|
if self.lineno is not None:
|
|
|
|
params['lineno'] = self.lineno + 1
|
|
|
|
|
|
|
|
if self.fspath and self.lineno and self.modpath:
|
|
|
|
line = "%(fspath)s:%(lineno)s: %(modpath)s"
|
|
|
|
elif self.fspath and self.modpath:
|
|
|
|
line = "%(fspath)s: %(modpath)s"
|
|
|
|
elif self.fspath and self.lineno:
|
|
|
|
line = "%(fspath)s:%(lineno)s"
|
|
|
|
else:
|
|
|
|
line = "[nometainfo]"
|
|
|
|
return line % params
|
|
|
|
|
|
|
|
|
|
|
|
class Node(object):
|
|
|
|
""" base class for Nodes in the collection tree.
|
|
|
|
Collector nodes have children and
|
|
|
|
Item nodes are terminal.
|
|
|
|
|
|
|
|
All nodes of the collection tree carry a _config
|
|
|
|
attribute for these reasons:
|
|
|
|
- to access custom Collection Nodes from a project
|
|
|
|
(defined in conftest's)
|
|
|
|
- to pickle themselves relatively to the "topdir"
|
|
|
|
- configuration/options for setup/teardown
|
|
|
|
stdout/stderr capturing and execution of test items
|
|
|
|
"""
|
|
|
|
ReprMetaInfo = ReprMetaInfo
|
|
|
|
def __init__(self, name, parent=None, config=None):
|
|
|
|
self.name = name
|
|
|
|
self.parent = parent
|
|
|
|
if config is None:
|
2009-03-18 07:48:07 +08:00
|
|
|
config = parent.config
|
|
|
|
self.config = config
|
2008-08-16 23:26:59 +08:00
|
|
|
self.fspath = getattr(parent, 'fspath', None)
|
|
|
|
|
2009-02-27 18:18:27 +08:00
|
|
|
|
2008-08-16 23:26:59 +08:00
|
|
|
#
|
|
|
|
# note to myself: Pickling is uh.
|
|
|
|
#
|
|
|
|
def __getstate__(self):
|
|
|
|
return (self.name, self.parent)
|
|
|
|
def __setstate__(self, (name, parent)):
|
2009-03-19 03:23:38 +08:00
|
|
|
try:
|
|
|
|
colitems = parent._memocollect()
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
raise
|
|
|
|
except Exception:
|
|
|
|
# seems our parent can't collect us
|
|
|
|
# so let's be somewhat operable
|
|
|
|
self.name = name
|
|
|
|
self.parent = parent
|
|
|
|
self.config = parent.config
|
2009-03-19 04:49:38 +08:00
|
|
|
#self._obj = "could not unpickle"
|
2009-03-19 03:23:38 +08:00
|
|
|
else:
|
|
|
|
for colitem in colitems:
|
|
|
|
if colitem.name == name:
|
|
|
|
# we are a copy that will not be returned
|
|
|
|
# by our parent
|
|
|
|
self.__dict__ = colitem.__dict__
|
|
|
|
break
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
def __repr__(self):
|
2009-03-18 07:48:07 +08:00
|
|
|
if getattr(self.config.option, 'debug', False):
|
2008-08-23 05:14:43 +08:00
|
|
|
return "<%s %r %0x>" %(self.__class__.__name__,
|
|
|
|
getattr(self, 'name', None), id(self))
|
|
|
|
else:
|
|
|
|
return "<%s %r>" %(self.__class__.__name__,
|
|
|
|
getattr(self, 'name', None))
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
# methods for ordering nodes
|
|
|
|
|
|
|
|
def __eq__(self, other):
|
|
|
|
if not isinstance(other, Node):
|
|
|
|
return False
|
|
|
|
return self.name == other.name and self.parent == other.parent
|
|
|
|
|
|
|
|
def __ne__(self, other):
|
|
|
|
return not self == other
|
|
|
|
|
|
|
|
def __hash__(self):
|
|
|
|
return hash((self.name, self.parent))
|
|
|
|
|
|
|
|
def __cmp__(self, other):
|
|
|
|
if not isinstance(other, Node):
|
|
|
|
return -1
|
|
|
|
s1 = self._getsortvalue()
|
|
|
|
s2 = other._getsortvalue()
|
|
|
|
return cmp(s1, s2)
|
|
|
|
|
|
|
|
def setup(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def teardown(self):
|
|
|
|
pass
|
|
|
|
|
2008-09-02 16:58:14 +08:00
|
|
|
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
|
|
|
|
|
2009-02-27 18:18:27 +08:00
|
|
|
def listchain(self, rootfirst=False):
|
|
|
|
""" return list of all parent collectors up to self,
|
|
|
|
starting form root of collection tree. """
|
2008-08-16 23:26:59 +08:00
|
|
|
l = [self]
|
|
|
|
while 1:
|
|
|
|
x = l[-1]
|
|
|
|
if x.parent is not None:
|
|
|
|
l.append(x.parent)
|
|
|
|
else:
|
2009-02-27 18:18:27 +08:00
|
|
|
if not rootfirst:
|
|
|
|
l.reverse()
|
2008-08-16 23:26:59 +08:00
|
|
|
return l
|
|
|
|
|
|
|
|
def listnames(self):
|
|
|
|
return [x.name for x in self.listchain()]
|
|
|
|
|
|
|
|
def _getitembynames(self, namelist):
|
|
|
|
cur = self
|
|
|
|
for name in namelist:
|
|
|
|
if name:
|
2008-09-02 20:24:15 +08:00
|
|
|
next = cur.collect_by_name(name)
|
2008-08-16 23:26:59 +08:00
|
|
|
if next is None:
|
2008-09-02 16:58:14 +08:00
|
|
|
existingnames = [x.name for x in self._memocollect()]
|
2008-08-16 23:26:59 +08:00
|
|
|
msg = ("Collector %r does not have name %r "
|
|
|
|
"existing names are: %s" %
|
|
|
|
(cur, name, existingnames))
|
|
|
|
raise AssertionError(msg)
|
|
|
|
cur = next
|
|
|
|
return cur
|
|
|
|
|
2009-02-27 18:18:27 +08:00
|
|
|
|
|
|
|
def _getfsnode(self, path):
|
|
|
|
# this method is usually called from
|
|
|
|
# config.getfsnode() which returns a colitem
|
|
|
|
# from filename arguments
|
|
|
|
#
|
|
|
|
# pytest's collector tree does not neccessarily
|
|
|
|
# follow the filesystem and we thus need to do
|
|
|
|
# some special matching code here because
|
|
|
|
# _getitembynames() works by colitem names, not
|
|
|
|
# basenames.
|
|
|
|
if path == self.fspath:
|
|
|
|
return self
|
|
|
|
basenames = path.relto(self.fspath).split(path.sep)
|
|
|
|
cur = self
|
|
|
|
while basenames:
|
|
|
|
basename = basenames.pop(0)
|
|
|
|
assert basename
|
|
|
|
fspath = cur.fspath.join(basename)
|
|
|
|
colitems = cur._memocollect()
|
|
|
|
l = []
|
|
|
|
for colitem in colitems:
|
|
|
|
if colitem.fspath == fspath or colitem.name == basename:
|
|
|
|
l.append(colitem)
|
|
|
|
if not l:
|
|
|
|
msg = ("Collector %r does not provide %r colitem "
|
|
|
|
"existing colitems are: %s" %
|
|
|
|
(cur, fspath, colitems))
|
|
|
|
raise AssertionError(msg)
|
|
|
|
if basenames:
|
|
|
|
if len(l) > 1:
|
|
|
|
msg = ("Collector %r has more than one %r colitem "
|
|
|
|
"existing colitems are: %s" %
|
|
|
|
(cur, fspath, colitems))
|
|
|
|
raise AssertionError(msg)
|
|
|
|
cur = l[0]
|
|
|
|
else:
|
|
|
|
if len(l) > 1:
|
|
|
|
cur = l
|
|
|
|
else:
|
|
|
|
cur = l[0]
|
|
|
|
break
|
|
|
|
return cur
|
|
|
|
|
|
|
|
def readkeywords(self):
|
|
|
|
return dict([(x, True) for x in self._keywords()])
|
|
|
|
|
2008-08-16 23:26:59 +08:00
|
|
|
def _keywords(self):
|
|
|
|
return [self.name]
|
|
|
|
|
|
|
|
def _skipbykeyword(self, keywordexpr):
|
|
|
|
""" return True if they given keyword expression means to
|
|
|
|
skip this collector/item.
|
|
|
|
"""
|
|
|
|
if not keywordexpr:
|
|
|
|
return
|
|
|
|
chain = self.listchain()
|
|
|
|
for key in filter(None, keywordexpr.split()):
|
|
|
|
eor = key[:1] == '-'
|
|
|
|
if eor:
|
|
|
|
key = key[1:]
|
|
|
|
if not (eor ^ self._matchonekeyword(key, chain)):
|
|
|
|
return True
|
|
|
|
|
|
|
|
def _matchonekeyword(self, key, chain):
|
|
|
|
elems = key.split(".")
|
|
|
|
# XXX O(n^2), anyone cares?
|
|
|
|
chain = [item._keywords() for item in chain if item._keywords()]
|
|
|
|
for start, _ in enumerate(chain):
|
|
|
|
if start + len(elems) > len(chain):
|
|
|
|
return False
|
|
|
|
for num, elem in enumerate(elems):
|
|
|
|
for keyword in chain[num + start]:
|
|
|
|
ok = False
|
|
|
|
if elem in keyword:
|
|
|
|
ok = True
|
|
|
|
break
|
|
|
|
if not ok:
|
|
|
|
break
|
|
|
|
if num == len(elems) - 1 and ok:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
def _getsortvalue(self):
|
|
|
|
return self.name
|
|
|
|
|
|
|
|
def _prunetraceback(self, traceback):
|
|
|
|
return traceback
|
|
|
|
|
|
|
|
def _totrail(self):
|
|
|
|
""" provide a trail relative to the topdir,
|
|
|
|
which can be used to reconstruct the
|
|
|
|
collector (possibly on a different host
|
|
|
|
starting from a different topdir).
|
|
|
|
"""
|
|
|
|
chain = self.listchain()
|
2009-03-18 07:48:07 +08:00
|
|
|
topdir = self.config.topdir
|
2008-08-16 23:26:59 +08:00
|
|
|
relpath = chain[0].fspath.relto(topdir)
|
|
|
|
if not relpath:
|
|
|
|
if chain[0].fspath == topdir:
|
|
|
|
relpath = "."
|
|
|
|
else:
|
|
|
|
raise ValueError("%r not relative to topdir %s"
|
|
|
|
%(chain[0].fspath, topdir))
|
|
|
|
return relpath, tuple([x.name for x in chain[1:]])
|
|
|
|
|
|
|
|
def _fromtrail(trail, config):
|
|
|
|
relpath, names = trail
|
|
|
|
fspath = config.topdir.join(relpath)
|
|
|
|
col = config.getfsnode(fspath)
|
|
|
|
return col._getitembynames(names)
|
|
|
|
_fromtrail = staticmethod(_fromtrail)
|
|
|
|
|
|
|
|
def _repr_failure_py(self, excinfo, outerr):
|
|
|
|
excinfo.traceback = self._prunetraceback(excinfo.traceback)
|
2008-09-13 03:16:34 +08:00
|
|
|
# XXX temporary hack: getrepr() should not take a 'style' argument
|
|
|
|
# at all; it should record all data in all cases, and the style
|
|
|
|
# should be parametrized in toterminal().
|
2009-03-18 07:48:07 +08:00
|
|
|
if self.config.option.tbstyle == "short":
|
2008-09-13 03:16:34 +08:00
|
|
|
style = "short"
|
|
|
|
else:
|
|
|
|
style = "long"
|
2008-08-16 23:26:59 +08:00
|
|
|
repr = excinfo.getrepr(funcargs=True,
|
2009-03-18 07:48:07 +08:00
|
|
|
showlocals=self.config.option.showlocals,
|
2008-09-13 03:16:34 +08:00
|
|
|
style=style)
|
2008-08-16 23:26:59 +08:00
|
|
|
for secname, content in zip(["out", "err"], outerr):
|
|
|
|
if content:
|
|
|
|
repr.addsection("Captured std%s" % secname, content.rstrip())
|
|
|
|
return repr
|
|
|
|
|
|
|
|
repr_failure = _repr_failure_py
|
|
|
|
shortfailurerepr = "F"
|
|
|
|
|
|
|
|
class Collector(Node):
|
|
|
|
"""
|
2008-09-02 16:58:14 +08:00
|
|
|
Collector instances create children through collect()
|
|
|
|
and thus iteratively build a tree. attributes::
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
parent: attribute pointing to the parent collector
|
|
|
|
(or None if this is the root collector)
|
|
|
|
name: basename of this collector object
|
|
|
|
"""
|
|
|
|
Directory = configproperty('Directory')
|
|
|
|
Module = configproperty('Module')
|
2009-02-27 18:18:27 +08:00
|
|
|
#DoctestFile = configproperty('DoctestFile')
|
2008-08-16 23:26:59 +08:00
|
|
|
|
2008-09-02 16:58:14 +08:00
|
|
|
def collect(self):
|
|
|
|
""" returns a list of children (items and collectors)
|
|
|
|
for this collection node.
|
|
|
|
"""
|
|
|
|
raise NotImplementedError("abstract")
|
2008-08-16 23:26:59 +08:00
|
|
|
|
2008-09-02 20:24:15 +08:00
|
|
|
def collect_by_name(self, name):
|
|
|
|
""" return a child matching the given name, else None. """
|
|
|
|
for colitem in self._memocollect():
|
|
|
|
if colitem.name == name:
|
|
|
|
return colitem
|
|
|
|
|
2008-09-02 16:58:14 +08:00
|
|
|
def repr_failure(self, excinfo, outerr):
|
|
|
|
""" represent a failure. """
|
|
|
|
return self._repr_failure_py(excinfo, outerr)
|
2008-08-16 23:26:59 +08:00
|
|
|
|
2008-09-02 16:58:14 +08:00
|
|
|
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.
|
2008-08-16 23:26:59 +08:00
|
|
|
You can return an empty list. Callers of this method
|
|
|
|
must take care to catch exceptions properly.
|
|
|
|
"""
|
2008-09-02 16:58:14 +08:00
|
|
|
warnoldcollect()
|
|
|
|
return [colitem.name for colitem in self._memocollect()]
|
2008-08-16 23:26:59 +08:00
|
|
|
|
2008-09-02 16:58:14 +08:00
|
|
|
def join(self, name):
|
|
|
|
""" DEPRECATED: return a child collector or item for the given name.
|
2008-08-16 23:26:59 +08:00
|
|
|
If the return value is None there is no such child.
|
|
|
|
"""
|
2008-09-02 16:58:14 +08:00
|
|
|
warnoldcollect()
|
2008-09-02 20:24:15 +08:00
|
|
|
return self.collect_by_name(name)
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
class FSCollector(Collector):
|
|
|
|
def __init__(self, fspath, parent=None, config=None):
|
|
|
|
fspath = py.path.local(fspath)
|
|
|
|
super(FSCollector, self).__init__(fspath.basename, parent, config=config)
|
|
|
|
self.fspath = fspath
|
|
|
|
|
|
|
|
def __getstate__(self):
|
|
|
|
if self.parent is None:
|
|
|
|
# the root node needs to pickle more context info
|
2009-03-18 07:48:07 +08:00
|
|
|
topdir = self.config.topdir
|
2008-08-16 23:26:59 +08:00
|
|
|
relpath = self.fspath.relto(topdir)
|
|
|
|
if not relpath:
|
|
|
|
if self.fspath == topdir:
|
|
|
|
relpath = "."
|
|
|
|
else:
|
|
|
|
raise ValueError("%r not relative to topdir %s"
|
|
|
|
%(self.fspath, topdir))
|
2009-03-18 07:48:07 +08:00
|
|
|
return (self.name, self.config, relpath)
|
2008-08-16 23:26:59 +08:00
|
|
|
else:
|
|
|
|
return (self.name, self.parent)
|
|
|
|
|
|
|
|
def __setstate__(self, picklestate):
|
|
|
|
if len(picklestate) == 3:
|
|
|
|
# root node
|
|
|
|
name, config, relpath = picklestate
|
|
|
|
fspath = config.topdir.join(relpath)
|
|
|
|
fsnode = config.getfsnode(fspath)
|
|
|
|
self.__dict__.update(fsnode.__dict__)
|
|
|
|
else:
|
|
|
|
name, parent = picklestate
|
|
|
|
self.__init__(parent.fspath.join(name), parent=parent)
|
|
|
|
|
2008-09-02 20:24:15 +08:00
|
|
|
class File(FSCollector):
|
|
|
|
""" base class for collecting tests from a file. """
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
class Directory(FSCollector):
|
|
|
|
def recfilter(self, path):
|
|
|
|
if path.check(dir=1, dotfile=0):
|
|
|
|
return path.basename not in ('CVS', '_darcs', '{arch}')
|
|
|
|
|
2008-09-02 16:58:14 +08:00
|
|
|
def collect(self):
|
|
|
|
l = self._deprecated_collect()
|
|
|
|
if l is not None:
|
|
|
|
return l
|
|
|
|
l = []
|
2008-09-08 21:02:35 +08:00
|
|
|
for path in self.fspath.listdir(sort=True):
|
2009-02-27 18:18:27 +08:00
|
|
|
res = self.consider(path)
|
2008-09-02 16:58:14 +08:00
|
|
|
if res is not None:
|
2009-02-27 18:18:27 +08:00
|
|
|
if isinstance(res, (list, tuple)):
|
|
|
|
l.extend(res)
|
|
|
|
else:
|
|
|
|
l.append(res)
|
2008-09-02 16:58:14 +08:00
|
|
|
return l
|
|
|
|
|
2009-02-27 18:18:27 +08:00
|
|
|
def consider(self, path):
|
2008-09-02 16:58:14 +08:00
|
|
|
if path.check(file=1):
|
2009-03-06 06:15:42 +08:00
|
|
|
res = self.consider_file(path)
|
2008-09-02 16:58:14 +08:00
|
|
|
elif path.check(dir=1):
|
2009-03-06 06:15:42 +08:00
|
|
|
res = self.consider_dir(path)
|
2009-03-11 05:39:39 +08:00
|
|
|
else:
|
|
|
|
res = None
|
2009-03-06 06:15:42 +08:00
|
|
|
if isinstance(res, list):
|
|
|
|
# throw out identical modules
|
|
|
|
l = []
|
|
|
|
for x in res:
|
|
|
|
if x not in l:
|
|
|
|
l.append(x)
|
|
|
|
res = l
|
|
|
|
return res
|
2008-09-02 16:58:14 +08:00
|
|
|
|
2009-02-27 18:18:27 +08:00
|
|
|
def consider_file(self, path):
|
2009-03-18 07:48:07 +08:00
|
|
|
return self.config.pytestplugins.call_each(
|
2009-02-27 18:18:27 +08:00
|
|
|
'pytest_collect_file', path=path, parent=self)
|
|
|
|
|
|
|
|
def consider_dir(self, path, usefilters=None):
|
|
|
|
if usefilters is not None:
|
|
|
|
APIWARN("0.99", "usefilters argument not needed")
|
2009-03-18 07:48:07 +08:00
|
|
|
res = self.config.pytestplugins.call_firstresult(
|
2009-03-06 06:54:04 +08:00
|
|
|
'pytest_collect_recurse', path=path, parent=self)
|
|
|
|
if res is None or res:
|
2009-03-18 07:48:07 +08:00
|
|
|
return self.config.pytestplugins.call_each(
|
2009-03-06 06:54:04 +08:00
|
|
|
'pytest_collect_directory', path=path, parent=self)
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
class Item(Node):
|
|
|
|
""" a basic test item. """
|
2008-09-02 16:58:14 +08:00
|
|
|
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)
|
|
|
|
|
2008-08-16 23:26:59 +08:00
|
|
|
def repr_metainfo(self):
|
|
|
|
try:
|
|
|
|
return self.ReprMetaInfo(self.fspath, modpath=self.__class__.__name__)
|
|
|
|
except AttributeError:
|
|
|
|
code = py.code.Code(self.execute)
|
|
|
|
return self.ReprMetaInfo(code.path, code.firstlineno)
|
|
|
|
|
2008-09-02 16:58:14 +08:00
|
|
|
def runtest(self):
|
2008-08-16 23:26:59 +08:00
|
|
|
""" execute this test item."""
|
|
|
|
|
2008-09-02 16:58:14 +08:00
|
|
|
def warnoldcollect():
|
2008-09-10 17:47:37 +08:00
|
|
|
APIWARN("1.0",
|
|
|
|
"implement collector.collect() instead of "
|
|
|
|
"collector.run() and collector.join()",
|
|
|
|
stacklevel=2)
|
2008-09-02 16:58:14 +08:00
|
|
|
|
|
|
|
def warnoldtestrun():
|
2008-09-10 17:47:37 +08:00
|
|
|
APIWARN("1.0",
|
|
|
|
"implement item.runtest() instead of "
|
|
|
|
"item.run() and item.execute()",
|
|
|
|
stacklevel=2)
|