[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:
hpk 2008-09-02 10:58:14 +02:00
parent ee94d1d2bd
commit 494ea31042
20 changed files with 631 additions and 535 deletions

View File

@ -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()")

View File

@ -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()

View File

@ -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

View File

@ -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 == []

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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 !!!
""")

View File

@ -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",

View File

@ -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)

View File

@ -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",

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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")

View File

@ -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")

View File

@ -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="""