[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)
|
||||
|
||||
def __repr__(self):
|
||||
if self._config.option.debug:
|
||||
if getattr(self._config.option, 'debug', False):
|
||||
return "<%s %r %0x>" %(self.__class__.__name__,
|
||||
getattr(self, 'name', None), id(self))
|
||||
else:
|
||||
|
@ -153,6 +153,24 @@ class Node(object):
|
|||
def teardown(self):
|
||||
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):
|
||||
""" return list of all parent collectors up to self. """
|
||||
l = [self]
|
||||
|
@ -173,7 +191,7 @@ class Node(object):
|
|||
if name:
|
||||
next = cur.join(name)
|
||||
if next is None:
|
||||
existingnames = cur.listdir()
|
||||
existingnames = [x.name for x in self._memocollect()]
|
||||
msg = ("Collector %r does not have name %r "
|
||||
"existing names are: %s" %
|
||||
(cur, name, existingnames))
|
||||
|
@ -262,9 +280,8 @@ class Node(object):
|
|||
|
||||
class Collector(Node):
|
||||
"""
|
||||
Collector instances generate children through
|
||||
their listdir() and join() methods and thus
|
||||
form a tree. attributes::
|
||||
Collector instances create children through collect()
|
||||
and thus iteratively build a tree. attributes::
|
||||
|
||||
parent: attribute pointing to the parent collector
|
||||
(or None if this is the root collector)
|
||||
|
@ -274,31 +291,60 @@ class Collector(Node):
|
|||
Module = configproperty('Module')
|
||||
DoctestFile = configproperty('DoctestFile')
|
||||
|
||||
def run(self):
|
||||
""" deprecated: use listdir(). """
|
||||
py.std.warnings.warn("deprecated: use listdir()", category=DeprecationWarning)
|
||||
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.
|
||||
def collect(self):
|
||||
""" returns a list of children (items and collectors)
|
||||
for this collection node.
|
||||
"""
|
||||
raise NotImplementedError("abstract")
|
||||
|
||||
def repr_failure(self, excinfo, outerr):
|
||||
""" represent a failure. """
|
||||
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):
|
||||
def __init__(self, fspath, parent=None, config=None):
|
||||
fspath = py.path.local(fspath)
|
||||
|
@ -336,49 +382,53 @@ class FSCollector(Collector):
|
|||
|
||||
|
||||
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):
|
||||
if path.check(dir=1, dotfile=0):
|
||||
return path.basename not in ('CVS', '_darcs', '{arch}')
|
||||
|
||||
def listdir(self):
|
||||
files = []
|
||||
dirs = []
|
||||
for p in self.fspath.listdir():
|
||||
if self.filefilter(p):
|
||||
files.append(p.basename)
|
||||
elif self.recfilter(p):
|
||||
dirs.append(p.basename)
|
||||
files.sort()
|
||||
dirs.sort()
|
||||
return files + dirs
|
||||
def collect(self):
|
||||
l = self._deprecated_collect()
|
||||
if l is not None:
|
||||
return l
|
||||
l = []
|
||||
for path in self.fspath.listdir(): # listdir() returns sorted order
|
||||
res = self.consider(path, usefilters=True)
|
||||
if res is not None:
|
||||
l.append(res)
|
||||
return l
|
||||
|
||||
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):
|
||||
name2items = self.__dict__.setdefault('_name2items', {})
|
||||
try:
|
||||
res = name2items[name]
|
||||
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
|
||||
""" get a child collector or item without using filters. """
|
||||
p = self.fspath.join(name)
|
||||
return self.consider(p, usefilters=False)
|
||||
|
||||
from py.__.test.runner import basic_run_report, forked_run_report
|
||||
class Item(Node):
|
||||
|
@ -388,6 +438,24 @@ class Item(Node):
|
|||
return forked_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):
|
||||
try:
|
||||
return self.ReprMetaInfo(self.fspath, modpath=self.__class__.__name__)
|
||||
|
@ -395,7 +463,7 @@ class Item(Node):
|
|||
code = py.code.Code(self.execute)
|
||||
return self.ReprMetaInfo(code.path, code.firstlineno)
|
||||
|
||||
def execute(self):
|
||||
def runtest(self):
|
||||
""" execute this test item."""
|
||||
|
||||
|
||||
|
@ -417,3 +485,13 @@ def getrelpath(curdir, dest):
|
|||
return target
|
||||
except AttributeError:
|
||||
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
|
||||
honouring setUp and tearDown semantics.
|
||||
"""
|
||||
def execute(self, _deprecated=None):
|
||||
def runtest(self, _deprecated=None):
|
||||
boundmethod = self.obj
|
||||
instance = boundmethod.im_self
|
||||
instance.setUp()
|
||||
|
|
|
@ -15,7 +15,7 @@ class DirSetup(object):
|
|||
|
||||
class BasicRsessionTest(object):
|
||||
def setup_class(cls):
|
||||
path = getexamplefile("funcexamples.py")
|
||||
path = getexamplefile("test_funcexamples.py")
|
||||
cls.config = py.test.config._reparse([path.dirpath()])
|
||||
cls.modulecol = cls.config.getfsnode(path)
|
||||
|
||||
|
@ -23,7 +23,7 @@ class BasicRsessionTest(object):
|
|||
self.session = self.config.initsession()
|
||||
|
||||
def getfunc(self, name):
|
||||
funcname = "func" + name
|
||||
funcname = "test_func" + name
|
||||
col = self.modulecol.join(funcname)
|
||||
assert col is not None, funcname
|
||||
return col
|
||||
|
|
|
@ -157,7 +157,7 @@ class TestDSession(InlineCollection):
|
|||
def test_fail():
|
||||
x
|
||||
""")
|
||||
item1, item2 = [modcol.join(x) for x in modcol.listdir()]
|
||||
item1, item2 = modcol.collect()
|
||||
|
||||
# setup a session with two hosts
|
||||
session = DSession(item1._config)
|
||||
|
@ -295,7 +295,7 @@ class TestDSession(InlineCollection):
|
|||
modcol._config.option.keyword = "nothing"
|
||||
dsel = session.filteritems([modcol])
|
||||
assert dsel == [modcol]
|
||||
items = [modcol.join(x) for x in modcol.listdir()]
|
||||
items = modcol.collect()
|
||||
events = [] ; session.bus.subscribe(events.append)
|
||||
remaining = session.filteritems(items)
|
||||
assert remaining == []
|
||||
|
|
|
@ -118,7 +118,7 @@ def deprecated_call(func, *args, **kwargs):
|
|||
warningmodule.warn_explicit = warn_explicit
|
||||
warningmodule.warn = warn
|
||||
if not l:
|
||||
print warningmodule
|
||||
#print warningmodule
|
||||
raise AssertionError("%r did not produce DeprecationWarning" %(func,))
|
||||
return ret
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ a tree of collectors and test items that this modules provides::
|
|||
"""
|
||||
import py
|
||||
from py.__.test.collect import Collector, FSCollector, Item, configproperty
|
||||
from py.__.test.collect import warnoldcollect
|
||||
|
||||
class PyobjMixin(object):
|
||||
def obj():
|
||||
|
@ -96,6 +97,15 @@ class PyCollectorMixin(PyobjMixin, Collector):
|
|||
def classnamefilter(self, name):
|
||||
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):
|
||||
# NB. we avoid random getattrs and peek in the __dict__ instead
|
||||
d = {}
|
||||
|
@ -113,67 +123,37 @@ class PyCollectorMixin(PyobjMixin, Collector):
|
|||
d[name] = res
|
||||
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):
|
||||
if (not usefilters or self.classnamefilter(name)) and \
|
||||
py.std.inspect.isclass(obj):
|
||||
res = self._deprecated_join(name)
|
||||
if res is not None:
|
||||
return res
|
||||
return self.Class(name, parent=self)
|
||||
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
|
||||
return self.Generator(name, parent=self)
|
||||
else:
|
||||
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):
|
||||
_stickyfailure = None
|
||||
|
||||
def listdir(self):
|
||||
def collect(self):
|
||||
if getattr(self.obj, 'disabled', 0):
|
||||
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):
|
||||
failure = self._stickyfailure
|
||||
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
|
||||
return self._memoizedcall('_obj', self.fspath.pyimport)
|
||||
|
||||
def setup(self):
|
||||
if not self._config.option.nomagic:
|
||||
|
@ -191,14 +171,13 @@ class Module(FSCollector, PyCollectorMixin):
|
|||
|
||||
class Class(PyCollectorMixin, Collector):
|
||||
|
||||
def listdir(self):
|
||||
def collect(self):
|
||||
if getattr(self.obj, 'disabled', 0):
|
||||
return []
|
||||
return ["()"]
|
||||
|
||||
def join(self, name):
|
||||
assert name == '()'
|
||||
return self.Instance(name, self)
|
||||
l = self._deprecated_collect()
|
||||
if l is not None:
|
||||
return l
|
||||
return [self.Instance(name="()", parent=self)]
|
||||
|
||||
def setup(self):
|
||||
setup_class = getattr(self.obj, 'setup_class', None)
|
||||
|
@ -215,7 +194,6 @@ class Class(PyCollectorMixin, Collector):
|
|||
def _getsortvalue(self):
|
||||
return self.getfslineno()
|
||||
|
||||
|
||||
class Instance(PyCollectorMixin, Collector):
|
||||
def _getobj(self):
|
||||
return self.parent.obj()
|
||||
|
@ -226,6 +204,10 @@ class Instance(PyCollectorMixin, Collector):
|
|||
return []
|
||||
Function = property(Function)
|
||||
|
||||
#def __repr__(self):
|
||||
# return "<%s of '%s'>" %(self.__class__.__name__,
|
||||
# self.parent.obj.__name__)
|
||||
|
||||
def newinstance(self):
|
||||
self.obj = self._getobj()
|
||||
return self.obj
|
||||
|
@ -278,24 +260,19 @@ class FunctionMixin(PyobjMixin):
|
|||
shortfailurerepr = "F"
|
||||
|
||||
class Generator(FunctionMixin, PyCollectorMixin, Collector):
|
||||
def listdir(self):
|
||||
self._prepare()
|
||||
itemlist = self._name2items
|
||||
return [itemlist["[%d]" % num].name for num in xrange(len(itemlist))]
|
||||
|
||||
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
|
||||
def collect(self):
|
||||
# test generators are collectors yet participate in
|
||||
# the test-item setup and teardown protocol.
|
||||
# otherwise we could avoid global setupstate
|
||||
self._setupstate.prepare(self)
|
||||
l = []
|
||||
for i, x in py.builtin.enumerate(self.obj()):
|
||||
call, args = self.getcallargs(x)
|
||||
if not callable(call):
|
||||
raise TypeError("%r yielded non callable test %r" %(self.obj, call,))
|
||||
name = "[%d]" % i
|
||||
d[name] = self.Function(name, self, args=args, callobj=call)
|
||||
return d
|
||||
l.append(self.Function(name, self, args=args, callobj=call))
|
||||
return l
|
||||
|
||||
def getcallargs(self, obj):
|
||||
if isinstance(obj, (tuple, list)):
|
||||
|
@ -318,9 +295,10 @@ class Function(FunctionMixin, Item):
|
|||
if callobj is not _dummy:
|
||||
self._obj = callobj
|
||||
|
||||
def execute(self):
|
||||
def runtest(self):
|
||||
""" execute the given test function. """
|
||||
self.obj(*self._args)
|
||||
if not self._deprecated_testexecution():
|
||||
self.obj(*self._args)
|
||||
|
||||
def __eq__(self, other):
|
||||
try:
|
||||
|
@ -335,12 +313,9 @@ class Function(FunctionMixin, Item):
|
|||
return not self == other
|
||||
|
||||
class DoctestFile(FSCollector):
|
||||
def listdir(self):
|
||||
return [self.fspath.basename]
|
||||
|
||||
def join(self, name):
|
||||
if name == self.fspath.basename:
|
||||
return DoctestFileContent(name, self)
|
||||
|
||||
def collect(self):
|
||||
return [DoctestFileContent(self.fspath.basename, parent=self)]
|
||||
|
||||
from py.__.code.excinfo import Repr, ReprFileLocation
|
||||
|
||||
|
@ -378,8 +353,9 @@ class DoctestFileContent(Item):
|
|||
else:
|
||||
return super(DoctestFileContent, self).repr_failure(excinfo, outerr)
|
||||
|
||||
def execute(self):
|
||||
failed, tot = py.compat.doctest.testfile(
|
||||
str(self.fspath), module_relative=False,
|
||||
raise_on_error=True, verbose=0)
|
||||
def runtest(self):
|
||||
if not self._deprecated_testexecution():
|
||||
failed, tot = py.compat.doctest.testfile(
|
||||
str(self.fspath), module_relative=False,
|
||||
raise_on_error=True, verbose=0)
|
||||
|
||||
|
|
|
@ -86,10 +86,10 @@ def test_getmodpath_cases():
|
|||
assert getmodpath(fcol) == expected
|
||||
|
||||
for names in (
|
||||
'mod.py test_f1 mod.test_f1',
|
||||
'mod.py TestA () test_m1 mod.TestA().test_m1',
|
||||
'mod.py test_g1 mod.test_g1',
|
||||
'mod.py test_g1 [0] mod.test_g1[0]',
|
||||
'test_mod.py test_f1 test_mod.test_f1',
|
||||
'test_mod.py TestA () test_m1 test_mod.TestA().test_m1',
|
||||
'test_mod.py test_g1 test_mod.test_g1',
|
||||
'test_mod.py test_g1 [0] test_mod.test_g1[0]',
|
||||
):
|
||||
names = names.split()
|
||||
expected = names.pop()
|
||||
|
|
|
@ -15,7 +15,7 @@ class TestCollectonly(InlineCollection):
|
|||
indent = rep.indent
|
||||
rep.processevent(event.CollectionStart(modcol))
|
||||
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")
|
||||
rep.processevent(event.ItemStart(item))
|
||||
|
@ -34,7 +34,7 @@ class TestCollectonly(InlineCollection):
|
|||
cols = list(self.session.genitems([modcol]))
|
||||
assert len(cols) == 0
|
||||
assert_stringio_contains_lines(stringio, """
|
||||
<Module 'TestCollectonly_test_collectonly_skipped_module.py'>
|
||||
<Module 'test_TestCollectonly_test_collectonly_skipped_module.py'>
|
||||
!!! Skipped: 'nomod' !!!
|
||||
""")
|
||||
|
||||
|
@ -47,7 +47,7 @@ class TestCollectonly(InlineCollection):
|
|||
cols = list(self.session.genitems([modcol]))
|
||||
assert len(cols) == 0
|
||||
assert_stringio_contains_lines(stringio, """
|
||||
<Module 'TestCollectonly_test_collectonly_failed_module.py'>
|
||||
<Module 'test_TestCollectonly_test_collectonly_failed_module.py'>
|
||||
!!! ValueError: 0 !!!
|
||||
""")
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ class TestTerminal(InlineCollection):
|
|||
stringio = py.std.cStringIO.StringIO()
|
||||
rep = TerminalReporter(modcol._config, file=stringio)
|
||||
rep.processevent(event.TestrunStart())
|
||||
items = [modcol.join(x) for x in modcol.listdir()]
|
||||
items = modcol.collect()
|
||||
for item in items:
|
||||
rep.processevent(event.ItemStart(item))
|
||||
s = stringio.getvalue().strip()
|
||||
|
@ -153,8 +153,7 @@ class TestTerminal(InlineCollection):
|
|||
""")
|
||||
stringio = py.std.cStringIO.StringIO()
|
||||
rep = TerminalReporter(modcol._config, file=stringio)
|
||||
reports = [basic_run_report(modcol.join(x))
|
||||
for x in modcol.listdir()]
|
||||
reports = [basic_run_report(x) for x in modcol.collect()]
|
||||
rep.processevent(event.LooponfailingInfo(reports, [modcol._config.topdir]))
|
||||
assert_stringio_contains_lines(stringio, [
|
||||
"*test_looponfailingreport.py:2: assert 0",
|
||||
|
|
|
@ -68,7 +68,7 @@ class ItemRunner(RobustRun):
|
|||
def teardown(self):
|
||||
self.colitem._setupstate.teardown_exact(self.colitem)
|
||||
def execute(self):
|
||||
self.colitem.execute()
|
||||
self.colitem.runtest()
|
||||
def makereport(self, res, when, excinfo, outerr):
|
||||
if excinfo:
|
||||
kw = self.getkw(when, excinfo, outerr)
|
||||
|
@ -84,7 +84,7 @@ class CollectorRunner(RobustRun):
|
|||
def teardown(self):
|
||||
pass
|
||||
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):
|
||||
if excinfo:
|
||||
kw = self.getkw(when, excinfo, outerr)
|
||||
|
|
|
@ -211,7 +211,7 @@ class TestPyTest(AcceptBase):
|
|||
""")
|
||||
result = self.runpytest(p1)
|
||||
assert_lines_contain_lines(result.outlines, [
|
||||
"test_fail.py F",
|
||||
".*test_fail.py F",
|
||||
"====* FAILURES *====",
|
||||
"____*____",
|
||||
"",
|
||||
|
@ -242,7 +242,7 @@ class TestPyTest(AcceptBase):
|
|||
""")
|
||||
result = self.runpytest(p1)
|
||||
assert_lines_contain_lines(result.outlines, [
|
||||
"test_one.py .F",
|
||||
".*test_one.py .F",
|
||||
"====* FAILURES *====",
|
||||
"____*____",
|
||||
"*test_one.py:8: ValueError",
|
||||
|
|
|
@ -81,7 +81,7 @@ namecontent = {
|
|||
|
||||
'failingimport.py': "import gruetzelmuetzel\n",
|
||||
|
||||
'mod.py': """
|
||||
'test_mod.py': """
|
||||
class TestA:
|
||||
def test_m1(self):
|
||||
pass
|
||||
|
@ -91,7 +91,7 @@ namecontent = {
|
|||
yield lambda x: None, 42
|
||||
""",
|
||||
|
||||
'filetest.py': """
|
||||
'file_test.py': """
|
||||
def test_one():
|
||||
assert 42 == 43
|
||||
|
||||
|
@ -125,60 +125,45 @@ namecontent = {
|
|||
pass
|
||||
""",
|
||||
|
||||
'funcexamples.py': """
|
||||
'test_funcexamples.py': """
|
||||
import py
|
||||
import time
|
||||
def funcpassed():
|
||||
def test_funcpassed():
|
||||
pass
|
||||
|
||||
def funcfailed():
|
||||
def test_funcfailed():
|
||||
raise AssertionError("hello world")
|
||||
|
||||
def funcskipped():
|
||||
def test_funcskipped():
|
||||
py.test.skip("skipped")
|
||||
|
||||
def funcprint():
|
||||
def test_funcprint():
|
||||
print "samfing"
|
||||
|
||||
def funcprinterr():
|
||||
def test_funcprinterr():
|
||||
print >>py.std.sys.stderr, "samfing"
|
||||
|
||||
def funcprintfail():
|
||||
def test_funcprintfail():
|
||||
print "samfing elz"
|
||||
asddsa
|
||||
|
||||
def funcexplicitfail():
|
||||
def test_funcexplicitfail():
|
||||
py.test.fail("3")
|
||||
|
||||
def funcraisesfails():
|
||||
def test_funcraisesfails():
|
||||
py.test.raises(ValueError, lambda: 123)
|
||||
|
||||
def funcoptioncustom():
|
||||
def test_funcoptioncustom():
|
||||
assert py.test.config.getvalue("custom")
|
||||
|
||||
def funchang():
|
||||
def test_funchang():
|
||||
import time
|
||||
time.sleep(1000)
|
||||
|
||||
def funckill15():
|
||||
def test_funckill15():
|
||||
import os
|
||||
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': """
|
||||
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):
|
||||
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)
|
||||
self.config = self.parseconfig(path, *configargs)
|
||||
if withsession:
|
||||
|
@ -204,7 +204,7 @@ class InlineCollection(FileCreation):
|
|||
|
||||
def getitems(self, source):
|
||||
modulecol = self.getmodulecol(source)
|
||||
return [modulecol.join(x) for x in modulecol.listdir()]
|
||||
return modulecol.collect()
|
||||
|
||||
def getitem(self, source, funcname="test_func"):
|
||||
modulecol = self.getmodulecol(source)
|
||||
|
|
|
@ -22,79 +22,9 @@ def setup_module(mod):
|
|||
mod.dummyconfig = DummyConfig()
|
||||
|
||||
def test_collect_versus_item():
|
||||
path = setupdata.getexamplefile("filetest.py")
|
||||
col = py.test.collect.Module(path, config=dummyconfig)
|
||||
assert not isinstance(col, py.test.collect.Item)
|
||||
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'
|
||||
from py.__.test.collect import Collector, Item
|
||||
assert not issubclass(Collector, Item)
|
||||
assert not issubclass(Item, Collector)
|
||||
|
||||
def test_ignored_certain_directories():
|
||||
tmp = py.test.ensuretemp("ignore_certain_directories")
|
||||
|
@ -107,80 +37,248 @@ def test_ignored_certain_directories():
|
|||
tmp.ensure('test_found.py')
|
||||
|
||||
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 'normal' in items
|
||||
assert 'test_found.py' in items
|
||||
assert 'normal' in names
|
||||
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():
|
||||
fn = tmpdir.join('nada','no')
|
||||
col = py.test.collect.Module(fn, config=dummyconfig)
|
||||
py.test.raises(py.error.ENOENT, col.listdir)
|
||||
|
||||
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]'
|
||||
py.test.raises(py.error.ENOENT, col.collect)
|
||||
|
||||
|
||||
def test_order_of_execution_generator_same_codeline():
|
||||
|
@ -238,52 +336,6 @@ def test_order_of_execution_generator_different_codeline():
|
|||
assert passed == 4
|
||||
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():
|
||||
config = py.test.config._reparse([tmpdir])
|
||||
f1 = py.test.collect.Function(name="name", config=config,
|
||||
|
@ -341,22 +393,6 @@ class Testgenitems:
|
|||
assert hash(i) != hash(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):
|
||||
# do we want to unify behaviour with
|
||||
# test_subdir_conftest_error?
|
||||
|
@ -407,57 +443,6 @@ class Testgenitems:
|
|||
assert items[1].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):
|
||||
self.tmp.ensure("whatever.txt")
|
||||
checkfile = self.tmp.ensure("test_something.txt")
|
||||
|
@ -548,7 +533,7 @@ class TestCollectorReprs(suptest.InlineCollection):
|
|||
assert info.lineno == 1
|
||||
assert info.modpath == "test_gen"
|
||||
|
||||
genitem = gencol.join(gencol.listdir()[0])
|
||||
genitem = gencol.collect()[0]
|
||||
info = genitem.repr_metainfo()
|
||||
assert info.fspath == modcol.fspath
|
||||
assert info.lineno == 2
|
||||
|
|
|
@ -74,32 +74,6 @@ def test_config_getvalue_honours_conftest():
|
|||
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():
|
||||
o = py.test.ensuretemp('testconfigget')
|
||||
o.ensure("conftest.py").write("x=1")
|
||||
|
@ -338,7 +312,7 @@ class TestSessionAndOptions:
|
|||
def test_conflict_options(self):
|
||||
def check_conflict_option(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])
|
||||
py.test.raises((ValueError, SystemExit), """
|
||||
config.initsession()
|
||||
|
@ -355,7 +329,7 @@ class TestSessionAndOptions:
|
|||
|
||||
def test_implied_options(self):
|
||||
def check_implied_option(opts, expr):
|
||||
path = setupdata.getexamplefile("filetest.py")
|
||||
path = setupdata.getexamplefile("file_test.py")
|
||||
config = py.test.config._reparse(opts + [path])
|
||||
session = config.initsession()
|
||||
assert eval(expr, session.config.option.__dict__)
|
||||
|
@ -374,14 +348,14 @@ class TestSessionAndOptions:
|
|||
passed, skipped, failed = sorter.countoutcomes()
|
||||
assert failed == 2
|
||||
assert skipped == passed == 0
|
||||
path = setupdata.getexamplefile("filetest.py")
|
||||
path = setupdata.getexamplefile("file_test.py")
|
||||
for opts in ([], ['-l'], ['-s'], ['--tb=no'], ['--tb=short'],
|
||||
['--tb=long'], ['--fulltrace'], ['--nomagic'],
|
||||
['--traceconfig'], ['-v'], ['-v', '-v']):
|
||||
yield runfiletest, opts + [path]
|
||||
|
||||
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])
|
||||
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)
|
||||
col = config.getfsnode(txtfile)
|
||||
testitem = col.join(txtfile.basename)
|
||||
res = testitem.execute()
|
||||
res = testitem.runtest()
|
||||
assert res is None
|
||||
|
||||
|
||||
|
@ -29,6 +29,6 @@ class TestDoctests(InlineCollection):
|
|||
2
|
||||
"""))
|
||||
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, ("", ""))
|
||||
assert repr.reprlocation
|
||||
|
|
|
@ -38,7 +38,7 @@ class TestEventBus:
|
|||
|
||||
class TestItemTestReport(object):
|
||||
def test_toterminal(self):
|
||||
sorter = suptest.events_run_example("filetest.py")
|
||||
sorter = suptest.events_run_example("file_test.py")
|
||||
reports = sorter.get(event.ItemTestReport)
|
||||
ev = reports[0]
|
||||
assert ev.failed
|
||||
|
@ -54,5 +54,5 @@ class TestItemTestReport(object):
|
|||
##assert ev.repr_run.find("AssertionError") != -1
|
||||
filepath = ev.colitem.fspath
|
||||
#filepath , modpath = ev.itemrepr_path
|
||||
assert str(filepath).endswith("filetest.py")
|
||||
#assert modpath.endswith("filetest.test_one")
|
||||
assert str(filepath).endswith("file_test.py")
|
||||
#assert modpath.endswith("file_test.test_one")
|
||||
|
|
|
@ -8,7 +8,7 @@ from py.__.code.testing.test_excinfo import TWMock
|
|||
class TestItemTestReport(object):
|
||||
|
||||
def test_toterminal(self):
|
||||
sorter = suptest.events_run_example("filetest.py")
|
||||
sorter = suptest.events_run_example("file_test.py")
|
||||
reports = sorter.get(event.ItemTestReport)
|
||||
ev = reports[0]
|
||||
assert ev.failed
|
||||
|
@ -24,7 +24,7 @@ class TestItemTestReport(object):
|
|||
##assert ev.repr_run.find("AssertionError") != -1
|
||||
filepath = ev.colitem.fspath
|
||||
#filepath , modpath = ev.itemrepr_path
|
||||
assert str(filepath).endswith("filetest.py")
|
||||
#assert modpath.endswith("filetest.test_one")
|
||||
assert str(filepath).endswith("file_test.py")
|
||||
#assert modpath.endswith("file_test.test_one")
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ def setup_module(mod):
|
|||
class TestKeywordSelection:
|
||||
def test_select_simple(self):
|
||||
def check(keyword, name):
|
||||
sorter = suptest.events_run_example("filetest.py",
|
||||
sorter = suptest.events_run_example("file_test.py",
|
||||
'-s', '-k', keyword)
|
||||
passed, skipped, failed = sorter.listoutcomes()
|
||||
assert len(failed) == 1
|
||||
|
@ -190,6 +190,21 @@ class SessionTests(suptest.InlineCollection):
|
|||
assert (out.find("[unknown exception raised in repr()]") != -1 or
|
||||
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):
|
||||
def test_pdb_run(self):
|
||||
tfile = self.makepyfile(test_one="""
|
||||
|
|
Loading…
Reference in New Issue