[py-svn] r8814 - in py/branch/py-collect/test2: . report/text testing testing/data testing/test testing/test/data

hpk at codespeak.net hpk at codespeak.net
Thu Feb 3 00:03:04 CET 2005


Author: hpk
Date: Thu Feb  3 00:03:04 2005
New Revision: 8814

Added:
   py/branch/py-collect/test2/terminal.py   (contents, props changed)
   py/branch/py-collect/test2/testing/data/
      - copied from r8784, py/branch/py-collect/test2/testing/test/data/
   py/branch/py-collect/test2/testing/test_drive.py   (contents, props changed)
   py/branch/py-collect/test2/testing/test_setup_nested.py
      - copied, changed from r8784, py/branch/py-collect/test2/testing/test/test_setup_nested.py
Removed:
   py/branch/py-collect/test2/compat.py
   py/branch/py-collect/test2/testing/test/data/
   py/branch/py-collect/test2/testing/test/test_setup_nested.py
   py/branch/py-collect/test2/testing/test_compat.py
Modified:
   py/branch/py-collect/test2/collect.py
   py/branch/py-collect/test2/config.py
   py/branch/py-collect/test2/defaultconfig.py
   py/branch/py-collect/test2/drive.py
   py/branch/py-collect/test2/item.py
   py/branch/py-collect/test2/report/text/reporter.py
   py/branch/py-collect/test2/report/text/summary.py
   py/branch/py-collect/test2/testing/test_collect.py
Log:
another train ride refactoring.  "Extpy" is not used anymore. 
Collector and Items are now much the same (issubclass(Item, 
Collector)).  This should allow more uniform error handling. 
It should now be easier to integrate Doctests
at collection level.  

more importantly, collectors now follow listdir()/join()
semantics (see the py.test broken thread on py-dev). 
Once the dust settles i'll try to remerge py.test2 to 
py.test and fix the documentation.  

The refactoring is still not complete, though. 



Modified: py/branch/py-collect/test2/collect.py
==============================================================================
--- py/branch/py-collect/test2/collect.py	(original)
+++ py/branch/py-collect/test2/collect.py	Thu Feb  3 00:03:04 2005
@@ -10,22 +10,24 @@
             Class 
                 Instance  # empty setup/teardown 
                     Function  
-                        Item 
                     Generator 
-                        GenItem 
+                        ANY 
             Function 
-                Item 
             Generator 
-                GenItem 
+                Function 
+        Directory       
+            ... 
 """ 
 
 def configproperty(name):
     def fget(self):
-        print "retrieving %r property from %s" %(name, self.fspath)
+        #print "retrieving %r property from %s" %(name, self.fspath)
         return py.test2.config.getconfigvalue(self.fspath, name)
     return property(fget)
 
 def getfscollector(fspath):
+    if isinstance(fspath, str): 
+        fspath = py.path.local(fspath)
     return Directory(fspath.dirpath()).join(fspath.basename) 
  
 class Collector(object): 
@@ -33,27 +35,102 @@
         self.name = name 
         self.parent = parent 
 
-    Item = py.test2.Item
-    GenItem = py.test2.GenItem
     Module = configproperty('Module')
     Directory = configproperty('Directory')
     Class = configproperty('Class')
+    Instance = configproperty('Instance')
+    Function = configproperty('Function')
     Generator = configproperty('Generator')
 
-    def setup(self, item): 
+    class Outcome(object):
+        def __init__(self, **kwargs):
+            assert 'msg' not in kwargs or isinstance(kwargs['msg'], str), (
+                "given 'msg' argument is not a string" )
+            self.__dict__.update(kwargs)
+        def __repr__(self):
+            return getattr(self, 'msg', object.__repr__(self))
+    class Passed(Outcome): pass
+    class Failed(Outcome): pass
+    class ExceptionFailure(Failed): msg = 'DID NOT RAISE'
+    class Skipped(Outcome): pass
+
+
+    def __repr__(self): 
+        return "<%s %r>" %(self.__class__.__name__, self.name) 
+
+    def __eq__(self, other): 
+        try: 
+            return self.name == other.name and self.parent == other.parent 
+        except AttributeError: 
+            return False 
+
+    def obj(): 
+        def fget(self):
+            try: 
+                return self._obj   
+            except AttributeError: 
+                self._obj = obj = self._getobj() 
+                return obj 
+        def fset(self, value): 
+            self._obj = value 
+        return property(fget, fset, None, "underlying object") 
+    obj = obj()
+
+    def _getobj(self): 
+        return getattr(self.parent.obj, self.name) 
+
+    def sortvalue(self): 
+        """ sorting function helper to bring test methods in
+            the same order as in their file.
+        """
+        for x in self.run():
+            return x.sortvalue() 
+
+    def getpathlineno(self): 
+        print "getpathlineno", self
+        return self.fspath, py.std.sys.maxint 
+
+    def setup(self): 
         pass 
 
-    def teardown(self, item): 
+    def teardown(self): 
         pass 
 
+    def listchain(self): 
+        """ return list of all parent collectors up to ourself. """ 
+        l = [self]
+        while 1: 
+            x = l[-1]
+            if x.parent is not None: 
+                l.append(x.parent) 
+            else: 
+                l.reverse() 
+                return l 
+
+    def getmodpath(self):
+        """ return path from the last module."""
+        inmodule = False 
+        newl = []
+        for x in self.listchain(): 
+            if not inmodule and not isinstance(x, Module): 
+                continue
+            if not inmodule:  
+                inmodule = True
+                continue
+            if newl and x.name[:1] in '([': 
+                newl[-1] += x.name 
+            else: 
+                newl.append(x.name) 
+        return ".".join(newl) 
+
     def iteritems(self):
-        """ yield all Items of a flattened Collector instance. """
-        for x in self.listdir(): 
-            if isinstance(x, Collector):
-                for y in x.iteritems():
-                    yield y
-            else:
-                yield x
+        """ yield all Items from a flattened Collector instance."""
+        if isinstance(self, py.test2.Item): 
+            yield self 
+        else: 
+            for x in self.run(): 
+                for y in x.iteritems(): 
+                    yield y 
 
     def fspath(): 
         def fget(self): 
@@ -89,17 +166,11 @@
     def recfilter(self, path): 
         return path.check(dotfile=0) 
 
-    def listdir(self): 
-        l = []
-        dirlist = self.fspath.listdir() 
-        for x in dirlist: 
-            if x.check(file=1) and self.filefilter(x): 
-                pass 
-            elif x.check(dir=1) and self.recfilter(x): 
-                pass 
-            else: 
-                continue 
-            l.append(self.join(x.basename)) 
+    def run(self): 
+        l = [self.join(x.basename) for x in self.fspath.listdir() 
+                if (x.check(file=1) and self.filefilter(x) or 
+                    x.check(dir=1) and self.recfilter(x))] 
+        l.sort()
         return filter(None, l)
 
     def join(self, name): 
@@ -109,33 +180,14 @@
         elif x.check(dir=1): 
             return self.Directory(x, parent=self) 
 
-    def __repr__(self): 
-        return "<collect.%s at %s" %(self.__class__.__name__, 
-                                     self.fspath)
-
-    # XXX setup/teardown directories? Use cases? 
-    def setup(self, item): 
-        pass 
-    def teardown(self, item): 
-        pass 
-
 class PyCollectorMixin(object): 
     def funcnamefilter(self, name): 
         return name.startswith('test_') 
     def classnamefilter(self, name): 
         return name.startswith('Test')
 
-    def __repr__(self): 
-        return "<collect.%s %r>" %(self.__class__.__name__, self.obj.__name__)
-
-    def obj(self): 
-        return getattr(self.parent.obj, self.name) 
-    obj = property(obj)
-
-    def listdir(self): 
+    def run(self): 
         l = []
-        if getattr(self.obj, 'disabled', 0):
-            return l 
         for name in dir(self.obj): 
             if self.funcnamefilter(name) or self.classnamefilter(name): 
                 x = self.join(name) 
@@ -154,13 +206,6 @@
             else: 
                 return self.Function(name, parent=self) 
 
-    def sortvalue(self): 
-        """ sorting function helper to bring test methods in
-            the same order as in their file.
-        """
-        for x in self.listdir():
-            return x.sortvalue() 
-
 class Module(PyCollectorMixin, FSCollector): 
     def obj(self): 
         try: 
@@ -170,60 +215,56 @@
             return obj 
     obj = property(obj, None, None, "module object")
 
-    def setup(self, item): 
-        item.setup_module(self.obj) 
-    def teardown(self, item): 
-        item.teardown_module(self.obj) 
+    def setup(self): 
+        if hasattr(self, 'setup_module'): 
+            self.setup_module(self.obj) 
+
+    def teardown(self): 
+        if hasattr(self, 'teardown_module'): 
+            self.teardown_module(self.obj) 
 
 class Class(PyCollectorMixin, Collector): 
-
-    def listdir(self): 
-        return self.join("()") 
+    def run(self): 
+        if getattr(self.obj, 'disabled', 0):
+            return []
+        return [self.join("()")]
 
     def join(self, name): 
         assert name == '()' 
         return self.Instance(name, self) 
 
-    def setup(self, item): 
-        item.setup_class(self.obj) 
-
-    def teardown(self, item): 
-        item.teardown_class(self.obj) 
+    def setup(self): 
+        setup_class = self.obj.__dict__.get('setup_class', None)
+        if setup_class is not None: 
+            setup_class(self.obj) 
+
+    def teardown(self): 
+        teardown_class = self.obj.__dict__.get('teardown_class', None)
+        if teardown_class is not None: 
+            teardown_class(self.obj) 
 
 class Instance(PyCollectorMixin, Collector): 
-    def Item(self): 
-        return getattr(self.obj, 'Item', super(Class, self).Item) 
-    Item = property(Item)
-
-def makebound(x): 
-    assert callable(x) 
-    if hasattr(x, 'im_self') and x.im_self is None: 
-        return x.__get__(x.im_class(), x.im_class) 
-    return x 
+    def _getobj(self): 
+        return self.parent.obj() 
+    def Function(self): 
+        return getattr(self.obj, 'Function', super(Instance, self).Function) 
+    Function = property(Function)
 
 class Generator(Collector): 
-    def obj(self): 
-        return makebound(getattr(self.parent.obj, self.name))
-    obj = property(obj, None, None, "test generator function") 
-        
-    def listdir(self): 
-        l = []
-        for i, x in py.builtin.enumerate(self.obj()): 
-            name = "%s:%d" % (self.name, i) 
-            l.append(self.join(name)) 
-        return l
+    def run(self): 
+        return [self.join("[%d]" % i) 
+                    for i in range(len(list(self.obj())))]
 
     def join(self, name): 
-        myname, num = name.split(':')
-        if myname != self.name: 
-            raise NameError("name %r is foreign to %r" %(name,self))
-        num = int(num)
+        if name[:1] != '[' or name[-1:] != ']': 
+            raise NameError("%r is not an index" %(name,))
+        num = int(name[1:-1]) 
         for i, x in py.builtin.enumerate(self.obj()): 
             if i == num: 
-                if isinstance(x, (Collector, self.Item)): 
+                if isinstance(x, (Collector, )): 
                     return x 
                 call, args = self.getcallargs(x) 
-                return self.GenItem(name, self, call, args)
+                return self.Function(name, self, args, call)
 
     def getcallargs(self, obj):
         if isinstance(obj, (tuple, list)):
@@ -233,10 +274,9 @@
         assert callable(call) 
         return call, args 
 
-    def sortvalue(self): 
-        obj = self.obj 
-        obj = getattr(obj, 'im_func', obj) 
-        obj = obj.func_code 
-        return (getattr(obj, 'co_filename', None), 
-                getattr(obj, 'co_firstlineno', py.std.sys.maxint))
+    def getpathlineno(self): 
+        code = py.code.Code(self.obj) 
+        return code.path, code.firstlineno 
 
+    def sortvalue(self):  
+        return self.getpathlineno() 

Deleted: /py/branch/py-collect/test2/compat.py
==============================================================================
--- /py/branch/py-collect/test2/compat.py	Thu Feb  3 00:03:04 2005
+++ (empty file)
@@ -1,58 +0,0 @@
-from __future__ import generators
-import py
-
-class TestCaseUnit(py.test.Item):
-    """ compatibility Unit executor for TestCase methods
-        honouring setUp and tearDown semantics.
-    """
-    def execute(self, driver):
-        unboundmethod = self.extpy.resolve()
-        cls = unboundmethod.im_class
-        instance = cls()
-        instance.setUp()
-        try:
-            unboundmethod(instance)
-        finally:
-            instance.tearDown()
-        return py.test.Item.Passed()
-
-class TestCase:
-    """compatibility class of unittest's TestCase. """
-    Item = TestCaseUnit
-
-    def setUp(self):
-        pass
-
-    def tearDown(self):
-        pass
-
-    def fail(self, msg=None):
-        """ fail immediate with given message. """
-        raise py.test.Item.Failed(msg=msg)
-
-    def assertRaises(self, excclass, func, *args, **kwargs):
-        py.test.raises(excclass, func, *args, **kwargs)
-    failUnlessRaises = assertRaises
-
-    # dynamically construct (redundant) methods
-    aliasmap = [
-        ('x',   'not x', 'assert_, failUnless'),
-        ('x',   'x',     'failIf'),
-        ('x,y', 'x!=y',  'failUnlessEqual,assertEqual, assertEquals'),
-        ('x,y', 'x==y',  'failIfEqual,assertNotEqual, assertNotEquals'),
-        ]
-    items = []
-    for sig, expr, names in aliasmap:
-        names = map(str.strip, names.split(','))
-        sigsubst = expr.replace('y', '%s').replace('x', '%s')
-        for name in names:
-            items.append("""
-                def %(name)s(self, %(sig)s):
-                    if %(expr)s:
-                        raise py.test.Item.Failed(tbindex=-2, msg=%(sigsubst)r %% (%(sig)s))
-            """ % locals() )
-
-    source = "".join(items)
-    exec py.code.Source(source).compile()
-
-__all__ = ['TestCase']

Modified: py/branch/py-collect/test2/config.py
==============================================================================
--- py/branch/py-collect/test2/config.py	(original)
+++ py/branch/py-collect/test2/config.py	Thu Feb  3 00:03:04 2005
@@ -14,8 +14,10 @@
 
 class Config:
     def __init__(self):
-        self.configpaths = []
+        self.configpaths = [defaultconfig]
         self.option = optparse.Values()
+        self.parseargs([]) 
+        self.configpaths.pop() 
 
     def _gettmpdir(self, sessiondir=[]):
         try:
@@ -113,7 +115,6 @@
             assert exe.check()
             self.option.executable = exe
 
-config = Config()
 
 # helpers
 
@@ -123,3 +124,6 @@
             yield y
     for x in parser.option_list:
         yield x
+
+# the default that is visible globally (XXX?)
+config = Config()

Modified: py/branch/py-collect/test2/defaultconfig.py
==============================================================================
--- py/branch/py-collect/test2/defaultconfig.py	(original)
+++ py/branch/py-collect/test2/defaultconfig.py	Thu Feb  3 00:03:04 2005
@@ -1,10 +1,12 @@
 import py
-Option = py.test2.Option
+Option = py.test.Option
 
-Module = py.test2.collect.Module 
-Directory = py.test2.collect.Directory
-Class = py.test2.collect.Class
-Generator = py.test2.collect.Generator 
+Module = py.test2.Module 
+Directory = py.test2.Directory
+Class = py.test2.Class
+Generator = py.test2.Generator 
+Function = py.test2.Function 
+Instance = py.test2.Instance 
 
 def getreporter():
     return py.test.TextReporter()

Modified: py/branch/py-collect/test2/drive.py
==============================================================================
--- py/branch/py-collect/test2/drive.py	(original)
+++ py/branch/py-collect/test2/drive.py	Thu Feb  3 00:03:04 2005
@@ -1,110 +1,113 @@
-from __future__ import generators
 import py
-collect = py.test.collect
+from py.__impl__.test.tool.outerrcapture import SimpleOutErrCapture
 
-class Exit(Exception):
-    """ for immediate program exits without tracebacks and reporter/summary. """
-    def __init__(self, item=None):
-        self.item = None
-        Exception.__init__(self)
-
-def exit(*args):
-    """ exit immediately without tracebacks and reporter/summary. """
-    raise Exit(*args)
+class ShadowOptions(object): 
+    def __init__(self, obj): 
+        self._obj = obj 
+    def __getattr__(self, name): 
+        return getattr(self._obj, name)
 
-class Driver:
+class Driver(object):
     """
         A Driver gets test Items from Collectors, # executes the
         Items and sends the Outcome to the Reporter.
     """
-    option = py.test.config.option
-    Exit = Exit
+    def __init__(self): 
+        self._memo = []
+        self.option = ShadowOptions(py.test2.config.option)
 
-    def __init__(self, channel):
-        self.reporter = py.test.config.getfirst('getreporter') ()
-        self._channel = channel
-        self._failed = []
+    def shouldclose(self): 
+        return False 
 
-    def setup(self):
+    def header(self):
         """ setup any neccessary resources. """
+        if not self.option.nomagic:
+            py.magic.invoke(assertion=1)
 
-    def teardown(self):
+    def footer(self):
         """ teardown any resources we know about. """
-        # XXX a cleaner way to teardown setupmanagers?
-        py.test.Item.teardownall()
+        py.test2.Item.state.teardown_all()
+        if not self.option.nomagic:
+            py.magic.revoke(assertion=1)
+
+    def start(self, colitem): 
+        if not self.option.nocapture and isinstance(colitem, py.test2.Item):
+            assert not hasattr(colitem, 'iocapture')
+            colitem.iocapture = SimpleOutErrCapture()
+
+    def finish(self, colitem, res): 
+        try: 
+            res.out, res.err = colitem.iocapture.reset()
+        except AttributeError: 
+            pass 
+        self._memo.append((colitem, res))
+        if isinstance(res, (colitem.Failed,)): 
+            if self.option.exitfirstproblem:
+                exit("exit on first problem configured.", item=colitem)
+
+    def getresults(self, cls): 
+        return [x for x in self._memo if isinstance(x[1], cls)]
 
-    def run(self, collectors):
+    def warning(self, msg): 
+        raise Warning(msg) 
+
+    def runpath(self, path): 
+        from py.__impl__.test2.collect import getfscollector 
+        col = getfscollector(path)
+        return self.run(col) 
+
+    def run(self, *colitems):
         """ main loop for running tests. """
-        self.setup()
         try:
+            self.header() 
             try:
-                self.reporter.start()
-                for x in collectors:
-                    self.run_collector_or_item(x)
+                for colitem in colitems: 
+                    self.runone(colitem)
             finally:
-                self.teardown()
-        except self.Exit, ex:
+                self.footer() 
+        except Exit, ex:
             pass
-        self.reporter.end()
-        l = []
-        for x in self._failed:
-            l.append((str(x.extpy.root), str(x.extpy.modpath)))
-        return l
-
-    def run_collector_or_item(self, obj):
-        """ run (possibly many) testitems and/or collectors. """
-        if self._channel and self._channel.isclosed():
-            raise SystemExit, "Channel is closed"
-        if isinstance(obj, py.test.Item):
-            self.runitem(obj)
-        elif isinstance(obj, py.test.collect.Collector):
-            self.runcollector(obj)
-        elif isinstance(obj, py.test.collect.Collector.Error):
-            try:
-                self.reporter.report_collect_error(obj)
-            except (KeyboardInterrupt, self.Exit): 
-                raise
-            except:
-                print "*" * 80
-                print "internal Reporter Error"
-                print "*" * 80
-                import traceback
-                traceback.print_exc()
-                raise self.Exit 
-            if self.option.exitfirstproblem:
-                raise self.Exit()
-        elif obj is None: 
-            pass # ok, we allow None to mean skip this item/collector 
-        else:
-            raise TypeError("%r is not a Item or Collector instance" % obj)
 
-    def runcollector(self, collector):
-        close = self.reporter.open(collector)
-        try:
-            for obj in collector:
-                self.run_collector_or_item(obj)
+    def runone(self, colitem):
+        if self.shouldclose(): 
+            raise SystemExit, "received external close signal" 
+        self.start(colitem)
+        try: 
+            try:
+                res = self.runinner(colitem) 
+            except (KeyboardInterrupt, Exit): 
+                res = None
+                raise 
+            except colitem.Outcome, res: 
+                pass 
+            except: 
+                excinfo = py.code.ExceptionInfo() 
+                res = colitem.Failed(excinfo=excinfo) 
         finally:
-            if close:
-                close()
+            self.finish(colitem, res) 
 
-    def runitem(self, item):
-        if not self.option.collectonly:
-            self.reporter.startitem(item)
-            try:
-                item.run(self)
-            except item.Outcome, res:
-                if not hasattr(res, 'excinfo'):
-                    res.excinfo = py.code.ExceptionInfo()
-            except (KeyboardInterrupt, self.Exit): 
-                raise
-            except:  
-                res = item.Failed(excinfo=py.code.ExceptionInfo())
-            else:
-                res = item.Passed()
-            res.item = item
-            self.reporter.enditem(res)
-            if isinstance(res, (item.Failed,)):
-                self._failed.append(item)
-                if py.test.config.option.exitfirstproblem:
-                    raise self.Exit(res.item)
+    def runinner(self, colitem): 
+        if self.option.collectonly and isinstance(colitem, py.test2.Item): 
+            return 
+        res = colitem.run() 
+        try: 
+            seq = iter(res) 
+        except TypeError: 
+            if res is not None: 
+                self.warning("%r.run() returned neither "
+                     "sequence nor None: %r" % (colitem, res))
+            return colitem.Passed()
+        for obj in seq: 
+            #print "diving into", obj
+            self.runone(obj) 
+        return res 
+
+class Exit(Exception):
+    """ for immediate program exits without tracebacks and reporter/summary. """
+    def __init__(self, msg="unknown reason", item=None):
+        self.msg = msg 
+        Exception.__init__(self, msg)
+
+def exit(msg, item=None): 
+    raise Exit(msg=msg, item=item)
 

Modified: py/branch/py-collect/test2/item.py
==============================================================================
--- py/branch/py-collect/test2/item.py	(original)
+++ py/branch/py-collect/test2/item.py	Thu Feb  3 00:03:04 2005
@@ -2,99 +2,59 @@
 
 from inspect import isclass, ismodule
 
-class SetupState:
+class SetupState(object):
     """ shared state for setting up/tearing down tests. """
     def __init__(self):
-        self._setupstack = []
-        self._instance = None
+        self.stack = []
 
-class SetupItem(object):
-    state = SetupState()
-
-    def teardown_all(cls): 
-        stack = self.state._setuptack
-        while stack: 
-            col, item = stack.pop() 
-            col.teardown(item) 
-    teardown_all = classmethod(teardown_all)
-
-    def prepare(self): 
-        """ setup objects along the path to the test-method
+    def teardown_all(self): 
+        while self.stack: 
+            col, item = self.stack.pop() 
+            col.teardown() 
+     
+    def prepare(self, colitem): 
+        """ setup objects along the collector chain to the test-method
             Teardown any unneccessary previously setup objects. 
         """
-        needed_collectors = self.listcols() 
-        while stack: 
-            col, item = stack.pop() 
-            col.teardown(item) 
+        needed_collectors = colitem.listchain() 
+        while self.stack: 
+            col = self.stack.pop() 
             try: 
                 i = needed_collectors.index(col) 
             except ValueError: 
+                col.teardown() 
                 continue 
             else: 
                 for col in needed_collectors[i+1:]: 
-                    col.setup(item) 
-                    stack.append((col, item))
+                    col.setup() 
+                    self.stack.append(col) 
 
-    def setup_module(self, mod):
-        if hasattr(mod, 'setup_module'):
-            mod.setup_module(mod)
-
-    def teardown_module(self, mod):
-        if hasattr(mod, 'teardown_module'):
-            mod.teardown_module(mod)
-
-    def setup_class(self, cls):
-        if hasattr(cls, 'setup_class'):
-            cls.setup_class.im_func(cls)
-
-    def teardown_class(self, cls):
-        if hasattr(cls, 'teardown_class'):
-            cls.teardown_class.im_func(cls)
-   
+class Item(py.test2.Collector): 
+    state = SetupState()
 
-class Item(SetupItem):
+class Function(Item): 
     """ an Item is responsible for locating and executing
         a Python callable test object.
     """
-    class Outcome:
-        def __init__(self, **kwargs):
-            assert 'msg' not in kwargs or isinstance(kwargs['msg'], str), (
-                "given 'msg' argument is not a string" )
-            self.__dict__.update(kwargs)
-        def __repr__(self):
-            return getattr(self, 'msg', object.__repr__(self))
-    class Passed(Outcome): pass
-    class Failed(Outcome): pass
-    class ExceptionFailure(Failed): msg = 'DID NOT RAISE'
-    class Skipped(Outcome): pass
-
-    def __init__(self, name, parent, args=()):
+    def __init__(self, name, parent, args=(), obj=None):
         self.name = name 
         self.parent = parent 
         self.args = args
+        if obj is not None: 
+            self._obj = obj 
 
     def __repr__(self): 
         return "<%s %r>" %(self.__class__.__name__, self.name)
 
-    def obj(self): 
-        try: 
-            return self._obj   
-        except AttributeError: 
-            self._obj = obj = getattr(self.parent.obj, self.name) 
-            return obj 
-    obj = property(obj, None, None, "underlying callable") 
-          
+    def getpathlineno(self): 
+        code = py.code.Code(self.obj) 
+        return code.path, code.firstlineno 
+
     def sortvalue(self):  
-        obj = self.obj 
-        if hasattr(obj, 'im_func'):
-            obj = obj.im_func
-        if hasattr(obj, 'func_code'):
-            obj = obj.func_code
-        return (getattr(obj, 'co_filename', None), 
-                getattr(obj, 'co_firstlineno', py.std.sys.maxint))
+        return self.getpathlineno() 
 
     def run(self):
-        self.prepare() 
+        self.state.prepare(self) 
         self.execute(self.obj, *self.args)
 
     def execute(self, target, *args):
@@ -109,25 +69,13 @@
         """
         return "%s%r" % (self.extpy.modpath, self.args)
 
-class Function(Item): 
-    def setup(self, item): 
-        item.setup_function(self.obj) 
-
-    def teardown(self, item): 
-        item.teardown_function(self.obj) 
-
-    def setup_function(self, function):
+    def setup(self): 
         if hasattr(self.obj, 'setup_function'): 
-            self.obj.setup_function(self.obj) 
+            return self.parent.setup_function(self.obj) 
 
-    def teardown_function(self, function):
+    def teardown(self): 
         if hasattr(self.obj, 'teardown_function'): 
-            self.obj.teardown_function(self.obj) 
-    
-class GenItem(Item):
-    def __init__(self, name, parent, call, args): 
-        super(GenItem, self).__init__(name, parent, args) 
-        self._obj = call  
+            return self.parent.teardown_function(self.obj) 
 
 #
 # triggering specific outcomes while executing Items

Modified: py/branch/py-collect/test2/report/text/reporter.py
==============================================================================
--- py/branch/py-collect/test2/report/text/reporter.py	(original)
+++ py/branch/py-collect/test2/report/text/reporter.py	Thu Feb  3 00:03:04 2005
@@ -8,7 +8,6 @@
 from summary import Summary
 from out import getout
 
-
 class TextReporter(object):
     Summary = Summary
     typemap = {
@@ -69,9 +68,7 @@
     def open(self, collector):
         if self.option.collectonly:
             cols = self.__dict__.setdefault('_opencollectors', [])
-            if len(cols):
-                print '    ' * len(cols),
-            print repr(collector)
+            print '    ' * len(cols), repr(collector)
             cols.append(collector)
             return cols.pop
 

Modified: py/branch/py-collect/test2/report/text/summary.py
==============================================================================
--- py/branch/py-collect/test2/report/text/summary.py	(original)
+++ py/branch/py-collect/test2/report/text/summary.py	Thu Feb  3 00:03:04 2005
@@ -51,152 +51,6 @@
         self.out.sep('=', 'tests finished: %s in %4.2f seconds' %
                          (status, elapsed))
 
-    def skippedreasons(self):
-        texts = {}
-        for res in self.getlist(Item.Skipped):
-            tbindex = getattr(res, 'tbindex', -1)
-            raisingtb = res.excinfo.traceback[tbindex] 
-            fn = raisingtb.frame.code.path
-            lineno = raisingtb.lineno
-            d = texts.setdefault(res.excinfo.exconly(), {})
-            d[(fn,lineno)] = res 
-                
-        if texts:
-            self.out.line()
-            self.out.sep('_', 'reasons for skipped tests')
-            for text, dict in texts.items():
-                for (fn, lineno), res in dict.items(): 
-                    self.out.line('Skipped in %s:%d' %(fn,lineno))
-                self.out.line("reason: %s" % text) 
-                self.out.line()
-
-    def failures(self):
-        l = self.getlist(Item.Failed)
-        if l: 
-            self.out.sep('_')
-            for res in self.getlist(Item.Failed):
-                self.repr_failure(res.excinfo, res)
-
-    def repr_failure(self, excinfo, res=None):
-        traceback = excinfo.traceback
-        if res: 
-            self.cut_traceback(traceback, res.item) 
-        last = traceback[-1]
-        for entry in traceback: 
-            self.out.line("")
-            if entry == last: 
-                indent = self.repr_source(entry, 'E') 
-                self.repr_failure_explanation(excinfo, indent) 
-            else:
-                self.repr_source(entry, '>') 
-            self.out.line("") 
-            self.out.line("[%s:%d]" %(entry.frame.code.path, entry.lineno+1))  
-            self.repr_locals(entry) 
-            if entry == last: 
-                if res: 
-                    root = res.item.extpy.root 
-                    modpath = res.item.extpy.modpath 
-                    fn, lineno = res.item.extpy.getfilelineno() 
-                    if fn != entry.frame.code.path or \
-                       entry.frame.code.firstlineno != lineno: 
-                        self.out.line("[testcode  : %s:%d]" % (fn, lineno+1)) 
-                    if root == fn: 
-                        self.out.line("[modulepath: %s]" %(modpath))
-                    else:
-                        self.out.line("[modulepath: %s %s]" %(root.basename, modpath))
-                if res: 
-                    self.repr_out_err(res) 
-                self.out.sep("_")
-            else: 
-                self.out.sep("_ ")
-                                                
-
-    def repr_source(self, entry, marker=">"): 
-        try: 
-            source = entry.getsource() 
-        except py.error.ENOENT:
-            self.out.line("[failure to get at sourcelines from %r]\n" % entry)
-        else: 
-            source = source.deindent() 
-            for line in source[:-1]: 
-                self.out.line("    " + line) 
-            lastline = source[-1]
-            self.out.line(marker + "   " + lastline) 
-            try: 
-                s = str(source.getstatement(len(source)-1))
-            except KeyboardInterrupt: 
-                raise 
-            except: 
-                #self.out.line("[failed to get last statement]\n%s" %(source,))
-                s = str(source[-1])
-            #print "XXX %r" % s
-            return 4 + (len(s) - len(s.lstrip()))
-        return 0 
-
-    def cut_traceback(self, traceback, item=None, tbindex=None):
-        if self.option.fulltrace or item is None:
-            return
-        path, lineno = item.extpy.getfilelineno()
-        for i, entry in py.builtin.enumerate(traceback): 
-            if entry.frame.code.path == path and \
-               entry.frame.code.firstlineno == lineno: 
-               del traceback[:i]
-               break 
-        # get rid of all frames marked with __tracebackhide__ 
-        l = []
-        for entry in traceback: 
-            try: 
-                x = entry.frame.eval("__tracebackhide__") 
-            except: 
-                x = None 
-            if not x: 
-                l.append(entry) 
-        traceback[:] = l 
-        #if tbindex is not None and tbindex < -1: 
-        #    del traceback[tbindex:]
-
-    def repr_failure_explanation(self, excinfo, indent): 
-        info = None 
-        info = getattr(getattr(excinfo, 'value', ''), 'msg', '') 
-        if not info and not self.option.nomagic: 
-            try: 
-                info = excinfo.traceback[-1].reinterpret() # very detailed info
-            except KeyboardInterrupt:
-                raise
-            except:
-                if self.option.verbose > 1:
-                    self.out.line("[reinterpretation traceback]")
-                    py.std.traceback.print_exc(file=py.std.sys.stdout)
-                else:
-                    self.out.line("[reinterpretation failed, increase "
-                                  "verbosity to see details]")
-        indent = " " * indent 
-        if not info:
-            info = str(excinfo) 
-
-        lines = info.split('\n') 
-        self.out.line('~' + indent[:-1] + lines.pop(0)) 
-        for x in lines: 
-            self.out.line(indent + x) 
-
-    def repr_out_err(self, res): 
-        for name in 'out', 'err':
-            if hasattr(res, name):
-                out = getattr(res, name)
-                if out.strip():
-                    self.out.sep("- ", "recorded std%s" % name)
-                    self.out.line(out.strip())
-
-    def repr_locals(self, entry): 
-        if self.option.showlocals:
-            self.out.sep('- ', 'locals')
-            for name, value in entry.frame.f_locals.items():
-                if len(repr(value)) < 70 or not isinstance(value,
-                                                (list, tuple, dict)):
-                    self.out.line("%-10s = %r" %(name, value))
-                else:
-                    self.out.line("%-10s =\\" % (name,))
-                    py.std.pprint.pprint(value, stream=self.out)
 
     def Xrepr_traceback_raw(self, traceback): 
         recursioncache = {}

Added: py/branch/py-collect/test2/terminal.py
==============================================================================
--- (empty file)
+++ py/branch/py-collect/test2/terminal.py	Thu Feb  3 00:03:04 2005
@@ -0,0 +1,245 @@
+import py
+
+from py.__impl__.test2.report.text.out import getout 
+from py.__impl__.test2.report.text.summary import Summary
+from time import time as now
+Item = py.test2.Item
+
+class TerminalDriver(py.test2.Driver): 
+    def __init__(self, file=None): 
+        super(TerminalDriver, self).__init__() 
+        if file is None: 
+            file = py.std.sys.stdout 
+        self.out = getout(file) 
+        self._started = {}
+        self.summary = Summary(self.out)
+        self.summary.option = self.option 
+        self._opencollectors = []
+
+    # ---------------------
+    # PROGRESS information 
+    # ---------------------
+   
+    def start(self, colitem):
+        super(TerminalDriver, self).start(colitem) 
+        if self.option.collectonly: 
+            cols = self._opencollectors
+            self.out.line('    ' * len(cols) + repr(colitem))
+            cols.append(colitem) 
+        self._started[colitem] = now()
+  
+    def finish(self, colitem, res):
+        end = now()
+        super(TerminalDriver, self).finish(colitem, res) 
+        if self.option.collectonly: 
+            cols = self._opencollectors 
+            last = cols.pop()
+            #assert last == colitem, "expected %r, got %r" %(last, colitem)
+        
+
+    # -------------------
+    # HEADER information 
+    # -------------------
+    def header(self): 
+        super(TerminalDriver, self).header() 
+        self.out.sep("=", "test process starts")
+        option = py.test.config.option
+        if option.session:
+            mode = 'session/child process'
+        elif option.executable:
+            mode = 'child process'
+        else:
+            mode = 'inprocess'
+        self.out.line("testing-mode: %s" % mode)
+        self.out.line("executable  : %s  (%s)" %
+                          (py.std.sys.executable, repr_pythonversion()))
+
+        rev = py.__package__.getrev()
+        self.out.line("using py lib: %s <rev %s>" % (
+                       py.path.local(py.__file__).dirpath(), rev))
+
+        for i, x in py.builtin.enumerate(py.test.config.configpaths):
+            self.out.line("initial testconfig %d: %s" %(i, x))
+        additional = py.test.config.getfirst('additionalinfo')
+        if additional:
+            for key, descr in additional():
+                self.out.line("%s: %s" %(key, descr))
+        self.out.sep("=")
+        self.starttime = now()
+  
+    # -------------------
+    # FOOTER information 
+    # -------------------
+ 
+    def footer(self):
+        super(TerminalDriver, self).footer() 
+        self.endtime = now()
+        self.out.line() 
+        self.skippedreasons()
+        self.failures()
+        self.summaryline()
+
+    def summaryline(self): 
+        outlist = []
+        sum = 0
+        for typ in Item.Passed, Item.Failed, Item.Skipped:
+            l = self.getresults(typ)
+            if l:
+                outlist.append('%d %s' % (len(l), typ.__name__.lower()))
+            sum += len(l)
+        elapsed = self.endtime-self.starttime
+        status = "%s" % ", ".join(outlist)
+        self.out.sep('=', 'tests finished: %s in %4.2f seconds' %
+                         (status, elapsed))
+
+    def skippedreasons(self):
+        texts = {}
+        for colitem, res in self.getresults(Item.Skipped):
+            tbindex = getattr(res, 'tbindex', -1)
+            raisingtb = res.excinfo.traceback[tbindex] 
+            fn = raisingtb.frame.code.path
+            lineno = raisingtb.lineno
+            d = texts.setdefault(res.excinfo.exconly(), {})
+            d[(fn,lineno)] = res 
+                
+        if texts:
+            self.out.line()
+            self.out.sep('_', 'reasons for skipped tests')
+            for text, dict in texts.items():
+                for (fn, lineno), res in dict.items(): 
+                    self.out.line('Skipped in %s:%d' %(fn,lineno))
+                self.out.line("reason: %s" % text) 
+                self.out.line()
+
+    def failures(self):
+        l = self.getresults(Item.Failed)
+        if l: 
+            self.out.sep('_')
+            for colitem, res in l: 
+                self.repr_failure(colitem, res) 
+
+    def repr_failure(self, item, res): 
+        excinfo = res.excinfo 
+        traceback = excinfo.traceback
+        if item: 
+            self.cut_traceback(traceback, item) 
+        last = traceback[-1]
+        for entry in traceback: 
+            self.out.line("")
+            if entry == last: 
+                indent = self.repr_source(entry, 'E') 
+                self.repr_failure_explanation(excinfo, indent) 
+            else:
+                self.repr_source(entry, '>') 
+            self.out.line("") 
+            self.out.line("[%s:%d]" %(entry.frame.code.path, entry.lineno+1))  
+            self.repr_locals(entry) 
+            if entry == last: 
+                if item: 
+                    root = item.fspath 
+                    modpath = item.getmodpath() 
+                    fn, lineno = item.getpathlineno() 
+                    if fn != entry.frame.code.path or \
+                       entry.frame.code.firstlineno != lineno: 
+                        self.out.line("[testcode  : %s:%d]" % (fn, lineno+1)) 
+                    if root == fn: 
+                        self.out.line("[modulepath: %s]" %(modpath))
+                    else:
+                        self.out.line("[modulepath: %s %s]" %(root.basename, modpath))
+                self.repr_out_err(res) 
+                self.out.sep("_")
+            else: 
+                self.out.sep("_ ")
+                                                
+
+    def repr_source(self, entry, marker=">"): 
+        try: 
+            source = entry.getsource() 
+        except py.error.ENOENT:
+            self.out.line("[failure to get at sourcelines from %r]\n" % entry)
+        else: 
+            source = source.deindent() 
+            for line in source[:-1]: 
+                self.out.line("    " + line) 
+            lastline = source[-1]
+            self.out.line(marker + "   " + lastline) 
+            try: 
+                s = str(source.getstatement(len(source)-1))
+            except KeyboardInterrupt: 
+                raise 
+            except: 
+                #self.out.line("[failed to get last statement]\n%s" %(source,))
+                s = str(source[-1])
+            #print "XXX %r" % s
+            return 4 + (len(s) - len(s.lstrip()))
+        return 0 
+
+    def cut_traceback(self, traceback, item=None): 
+        if self.option.fulltrace or item is None:
+            return
+        path, lineno = item.getpathlineno() 
+        for i, entry in py.builtin.enumerate(traceback): 
+            if entry.frame.code.path == path and \
+               entry.frame.code.firstlineno == lineno: 
+               del traceback[:i]
+               break 
+        # get rid of all frames marked with __tracebackhide__ 
+        l = []
+        for entry in traceback: 
+            try: 
+                x = entry.frame.eval("__tracebackhide__") 
+            except: 
+                x = None 
+            if not x: 
+                l.append(entry) 
+        traceback[:] = l 
+
+    def repr_failure_explanation(self, excinfo, indent): 
+        info = None 
+        info = getattr(getattr(excinfo, 'value', ''), 'msg', '') 
+        if not info and not self.option.nomagic: 
+            try: 
+                info = excinfo.traceback[-1].reinterpret() # very detailed info
+            except KeyboardInterrupt:
+                raise
+            except:
+                if self.option.verbose > 1:
+                    self.out.line("[reinterpretation traceback]")
+                    py.std.traceback.print_exc(file=py.std.sys.stdout)
+                else:
+                    self.out.line("[reinterpretation failed, increase "
+                                  "verbosity to see details]")
+        indent = " " * indent 
+        if not info:
+            info = str(excinfo) 
+
+        lines = info.split('\n') 
+        self.out.line('~' + indent[:-1] + lines.pop(0)) 
+        for x in lines: 
+            self.out.line(indent + x) 
+
+    def repr_out_err(self, res): 
+        for name in 'out', 'err':
+            if hasattr(res, name):
+                out = getattr(res, name)
+                if out.strip():
+                    self.out.sep("- ", "recorded std%s" % name)
+                    self.out.line(out.strip())
+
+    def repr_locals(self, entry): 
+        if self.option.showlocals:
+            self.out.sep('- ', 'locals')
+            for name, value in entry.frame.f_locals.items():
+                if len(repr(value)) < 70 or not isinstance(value,
+                                                (list, tuple, dict)):
+                    self.out.line("%-10s = %r" %(name, value))
+                else:
+                    self.out.line("%-10s =\\" % (name,))
+                    py.std.pprint.pprint(value, stream=self.out)
+
+def repr_pythonversion():
+    v = py.std.sys.version_info
+    try:
+        return "%s.%s.%s-%s-%s" % v
+    except ValueError:
+        return str(v)

Deleted: /py/branch/py-collect/test2/testing/test/test_setup_nested.py
==============================================================================
--- /py/branch/py-collect/test2/testing/test/test_setup_nested.py	Thu Feb  3 00:03:04 2005
+++ (empty file)
@@ -1,52 +0,0 @@
-
-#
-# test correct setup/teardowns at
-# module, class, and instance level
-
-modlevel = []
-def setup_module(module):
-    module.modlevel.append(42)
-
-def teardown_module(module):
-    modlevel.pop()
-
-def setup_function(function):
-    function.answer = 17
-
-def teardown_function(function):
-    del function.answer
-
-def test_modlevel():
-    assert modlevel[0] == 42
-    assert test_modlevel.answer == 17
-
-
-class TestSimpleClassSetup:
-    clslevel = []
-    def setup_class(cls):
-        cls.clslevel.append(23)
-
-    def teardown_class(cls):
-        cls.clslevel.pop()
-
-    def test_classlevel(self):
-        assert self.clslevel[0] == 23
-
-    def test_modulelevel(self):
-        assert modlevel == [42]
-
-class TestInheritedClassSetupStillWorks(TestSimpleClassSetup):
-    def test_classlevel_anothertime(self):
-        assert self.clslevel == [23]
-
-class SetupTeardownOnInstance(TestSimpleClassSetup):
-    def setup_method(self, method):
-        self.clslevel.append(17)
-
-    def teardown_method(self, method):
-        x = self.clslevel.pop()
-        assert x == 17
-
-    def test_setup(self):
-        assert self.clslevel[-1] == 17
-

Modified: py/branch/py-collect/test2/testing/test_collect.py
==============================================================================
--- py/branch/py-collect/test2/testing/test_collect.py	(original)
+++ py/branch/py-collect/test2/testing/test_collect.py	Thu Feb  3 00:03:04 2005
@@ -1,20 +1,20 @@
 from __future__ import generators
 import py
-datadir  = py.magic.autopath().dirpath('test', 'data')
+datadir  = py.magic.autopath().dirpath('data')
 
 def test_failing_import_execfile():
     fn = datadir / 'failingimport.py'
-    col = py.test2.collect.Module(fn) 
+    col = py.test2.Module(fn) 
     def _import(): 
-        py.test2.raises(ImportError, col.listdir)
+        py.test2.raises(ImportError, col.run)
     _import()
     _import()
 
 def XXXtest_finds_root(): 
     fn = datadir / 'filetest.py'
-    col = py.test2.collect.Module(fn) 
+    col = py.test2.Module(fn) 
     root, namelist = col.fromroot() 
-    assert isinstance(root, py.test2.collect.Directory) 
+    assert isinstance(root, py.test2.Directory) 
     cur = root
     for x in namelist: 
         cur = cur.join(x) 
@@ -24,8 +24,8 @@
 
 def test_finds_tests(): 
     fn = datadir / 'filetest.py'
-    col = py.test2.collect.Module(fn) 
-    l = col.listdir() 
+    col = py.test2.Module(fn) 
+    l = col.run() 
     assert len(l) == 2 
     items = list(col.iteritems())
     assert len(items) == 2 
@@ -35,29 +35,29 @@
     assert l[1].fspath == fn 
 
 def test_failing_import_directory():
-    class MyDirectory(py.test2.collect.Directory):
+    class MyDirectory(py.test2.Directory):
         filefilter = py.path.checker(fnmatch='testspecial*.py') 
-    l = MyDirectory(datadir).listdir() 
+    l = MyDirectory(datadir).run() 
     assert len(l) == 1
-    assert isinstance(l[0], py.test2.collect.Module)
-    py.test.raises(ImportError, l[0].listdir)
+    assert isinstance(l[0], py.test2.Module)
+    py.test.raises(ImportError, l[0].run)
 
 def test_module_file_not_found():
     fn = datadir.join('nada','no')
-    col = py.test2.collect.Module(fn) 
-    py.test2.raises(py.error.ENOENT, col.listdir) 
+    col = py.test2.Module(fn) 
+    py.test2.raises(py.error.ENOENT, col.run) 
 
 def test_syntax_error_in_module():
     modpath = py.path.extpy(datadir.join('syntax_error.py'))
-    col = py.test2.collect.Module(modpath) 
-    py.test.raises(SyntaxError, col.listdir) 
+    col = py.test2.Module(modpath) 
+    py.test.raises(SyntaxError, col.run) 
 
 def test_disabled_class():
-    col = py.test2.collect.Module(datadir.join('disabled.py'))
-    l = col.listdir() 
+    col = py.test2.Module(datadir.join('disabled.py'))
+    l = col.run() 
     assert len(l) == 1
-    assert isinstance(l[0], py.test2.collect.Class)
-    assert l[0].listdir() == []
+    assert isinstance(l[0], py.test2.Class)
+    assert not l[0].run() 
 
 class Testsomeclass:
     disabled = True
@@ -92,29 +92,30 @@
                 yield func1, 17, 3*5
                 yield func1, 42, 6*7
     """))
-    col = py.test2.collect.Module(tfile) 
-    l = col.listdir() 
+    col = py.test2.Module(tfile) 
+    l = col.run() 
     assert len(l) == 2 
 
     generator = l[0]
-    assert isinstance(generator, py.test2.collect.Generator)
-    l2 = generator.listdir() 
+    print l
+    assert isinstance(generator, py.test2.Generator)
+    l2 = generator.run() 
     assert len(l2) == 2 
-    assert isinstance(l2[0], py.test2.GenItem)
-    assert isinstance(l2[1], py.test2.GenItem)
-    assert l2[0].name == 'test_gen:0'
-    assert l2[1].name == 'test_gen:1'
+    assert isinstance(l2[0], py.test2.Function)
+    assert isinstance(l2[1], py.test2.Function)
+    assert l2[0].name == '[0]'
+    assert l2[1].name == '[1]'
  
-    classlist = l[1].listdir() 
+    classlist = l[1].run() 
     assert len(classlist) == 1
-    generator = classlist[0]
-    assert isinstance(generator, py.test2.collect.Generator)
-    l2 = generator.listdir() 
+    generator = classlist[0].run()[0]
+    assert isinstance(generator, py.test2.Generator)
+    l2 = generator.run() 
     assert len(l2) == 2 
-    assert isinstance(l2[0], py.test2.GenItem)
-    assert isinstance(l2[1], py.test2.GenItem)
-    assert l2[0].name == 'test_gen:0'
-    assert l2[1].name == 'test_gen:1'
+    assert isinstance(l2[0], py.test2.Function)
+    assert isinstance(l2[1], py.test2.Function)
+    assert l2[0].name == '[0]'
+    assert l2[1].name == '[1]'
     
 l = []
 def test_1():
@@ -138,21 +139,21 @@
     o = py.test2.config.tmpdir.ensure('customconfigtest', dir=1)
     o.ensure('conftest.py').write("""if 1:
         import py
-        class MyItem(py.test2.Item):
+        class MyFunction(py.test2.Function):
             pass
-        class Directory(py.test2.collect.Directory):
+        class Directory(py.test2.Directory):
             def filefilter(self, fspath):
                 return fspath.check(basestarts='check_')
-        class Module(py.test2.collect.Module):
-            Item = MyItem
+        class myfuncmixin: 
+            Function = MyFunction
             def funcnamefilter(self, name): 
                 return name.startswith('check_') 
+
+        class Module(myfuncmixin, py.test2.Module):
             def classnamefilter(self, name): 
                 return name.startswith('CustomTestClass') 
-        class Class(py.test2.collect.Class):
-            Item = MyItem 
-            def funcnamefilter(self, name): 
-                return name.startswith('check_') 
+        class Instance(myfuncmixin, py.test2.Instance):
+            pass 
         """)
     o.ensure('somedir', 'check_something').write("""if 1:
         def check_func():
@@ -164,4 +165,4 @@
     from py.__impl__.test2.collect import getfscollector
     items = list(getfscollector(o).iteritems())
     assert len(items) == 2
-    assert items[1].__class__.__name__ == 'MyItem'
+    assert items[1].__class__.__name__ == 'MyFunction'

Deleted: /py/branch/py-collect/test2/testing/test_compat.py
==============================================================================
--- /py/branch/py-collect/test2/testing/test_compat.py	Thu Feb  3 00:03:04 2005
+++ (empty file)
@@ -1,51 +0,0 @@
-from __future__ import generators
-import py
-
-class TestCompatTestCaseSetupSemantics(py.test.compat.TestCase):
-    globlist = []
-
-    def setUp(self):
-        self.__dict__.setdefault('l', []).append(42)
-        self.globlist.append(self)
-
-    def tearDown(self):
-        self.l.pop()
-
-    def test_issetup(self):
-        l = self.l
-        assert len(l) == 1
-        assert l[-1] == 42
-        self.checkmultipleinstances()
-
-    def test_issetup2(self):
-        l = self.l
-        assert len(l) == 1
-        assert l[-1] == 42
-        self.checkmultipleinstances()
-
-    def checkmultipleinstances(self):
-        for x,y in zip(self.globlist, self.globlist[1:]):
-            assert x is not y
-
-class TestCompatAssertions(py.test.compat.TestCase):
-    nameparamdef = {
-        'failUnlessEqual,assertEqual,assertEquals': ('1, 1', '1, 0'),
-        'assertNotEquals,failIfEqual': ('0, 1', '0,0'),
-        'failUnless,assert_': ('1', 'None'),
-        'failIf': ('0', '1'),
-        }
-
-    sourcelist = []
-    for names, (paramok, paramfail) in nameparamdef.items():
-        for name in names.split(','):
-            source = """
-            def test_%(name)s(self):
-                self.%(name)s(%(paramok)s)
-                #self.%(name)s(%(paramfail)s)
-
-            def test_%(name)s_failing(self):
-                self.assertRaises(py.test.Item.Failed,
-                            self.%(name)s, %(paramfail)s)
-            """ % locals()
-            co = py.code.Source(source).compile()
-            exec co

Added: py/branch/py-collect/test2/testing/test_drive.py
==============================================================================
--- (empty file)
+++ py/branch/py-collect/test2/testing/test_drive.py	Thu Feb  3 00:03:04 2005
@@ -0,0 +1,53 @@
+import py
+datadir = py.magic.autopath().dirpath('data')
+from cStringIO import StringIO 
+
+class TestDefaultDriver: 
+    def test_simple(self): 
+        drive = py.test2.Driver() 
+        drive.option.nocapture = True 
+        drive.runpath(datadir / 'filetest.py')
+        l = drive.getresults(py.test2.Item.Failed)
+        assert len(l) == 2 
+        l = drive.getresults(py.test2.Item.Passed)
+        assert not l 
+    
+    def test_exit_first_problem(self): 
+        drive = py.test2.Driver() 
+        drive.option.exitfirstproblem = True 
+        drive.runpath(str(datadir / 'filetest.py'))
+        l = drive.getresults(py.test2.Item.Failed)
+        assert len(l) == 1 
+        l = drive.getresults(py.test2.Item.Passed)
+        assert not l 
+
+class TestTerminalDriver: 
+    def test_terminal(self): 
+        c = StringIO() 
+        drive = py.test2.TerminalDriver(file=c) 
+        drive.runpath(datadir / 'filetest.py')
+        out = c.getvalue() 
+        print "memo"
+        print drive._memo
+        print "out" 
+        print out 
+        l = drive.getresults(py.test2.Item.Failed)
+        assert len(l) == 2
+        assert out.find('2 failed') != -1 
+
+    def test_collectonly(self): 
+        c = StringIO() 
+        drive = py.test2.TerminalDriver(file=c) 
+        drive.option.collectonly = True 
+        drive.runpath(str(datadir / 'filetest.py'))
+        out = c.getvalue()
+        print out 
+        l = drive.getresults(py.test2.Item.Failed)
+        #if l: 
+        #    x = l[0][1].excinfo
+        #    print x.exconly() 
+        #    print x.traceback
+        assert len(l) == 0 
+        for line in ('filetest.py', 'test_one', 
+                     'TestClass', 'test_method_one'): 
+            assert out.find(line) 

Copied: py/branch/py-collect/test2/testing/test_setup_nested.py (from r8784, py/branch/py-collect/test2/testing/test/test_setup_nested.py)
==============================================================================
--- py/branch/py-collect/test2/testing/test/test_setup_nested.py	(original)
+++ py/branch/py-collect/test2/testing/test_setup_nested.py	Thu Feb  3 00:03:04 2005
@@ -20,7 +20,6 @@
     assert modlevel[0] == 42
     assert test_modlevel.answer == 17
 
-
 class TestSimpleClassSetup:
     clslevel = []
     def setup_class(cls):



More information about the pytest-commit mailing list