[pypy-svn] rev 2476 - pypy/trunk/src/pypy/tool

sschwarzer at codespeak.net sschwarzer at codespeak.net
Thu Dec 18 11:16:52 CET 2003


Author: sschwarzer
Date: Thu Dec 18 11:16:51 2003
New Revision: 2476

Modified:
   pypy/trunk/src/pypy/tool/newtest.py
Log:
Executing tests works.
Added generator method to TestSuite class.


Modified: pypy/trunk/src/pypy/tool/newtest.py
==============================================================================
--- pypy/trunk/src/pypy/tool/newtest.py	(original)
+++ pypy/trunk/src/pypy/tool/newtest.py	Thu Dec 18 11:16:51 2003
@@ -2,6 +2,8 @@
 import inspect
 import os
 import sys
+import cStringIO as StringIO
+import traceback
 import unittest
 import vpath
 
@@ -15,18 +17,25 @@
 
 class TestResult:
     """Represent the result of a run of a test item."""
-    def __init__(self, item, status=None, fullname=None, traceback=None):
-        # one of SUCCESS, ERROR, FAILURE, IGNORED, SKIPPED
+    def __init__(self, item):
+        self.item = item
+        # one of None, SUCCESS, ERROR, FAILURE, IGNORED, SKIPPED (see above)
         self.status = None
-        # name of the test method (without class or module name)
-        self.methodname = None
-        # full method name (with module path and class name)
-        self.fullname = None
-        # traceback object if applicable, else None
+        # traceback object for errors and failures, else None
         self.traceback = None
         # formatted traceback (a string)
         self.formatted_traceback = None
 
+    def _setstatus(self, statuscode):
+        self.status = statuscode
+        self.excinfo = sys.exc_info()
+        self.traceback = self.excinfo[2]
+        # store formatted traceback
+        output = StringIO.StringIO()
+        args = self.excinfo + (None, output)
+        traceback.print_exception(*args)
+        self.formatted_traceback = output.getvalue().strip()
+
 
 class TestItem:
     """Represent a single test method from a TestCase class."""
@@ -36,20 +45,73 @@
         self.module = module
         self.cls = cls
         self.method = testmethod
-        # we can only derive this from a frame or traceback?
+        #XXX we can only derive this from a frame or traceback?
         #self.lineno = None
 
-    def run(self):
-        """Run this TestItem and return a corresponding TestResult object."""
+    def run(self, pretest=None, posttest=None):
+        """
+        Run this TestItem and return a corresponding TestResult object.
+
+        pretest, if not None, is a callable which is called before
+        running the setUp method of the TestCase class. It is passed
+        the this TestItem instance as the argument.
+
+        Similarly, posttest is called after running the TestCase
+        class's tearDown method (or after the test method, if that
+        doesn't complete successfully). Like for pretest, the
+        callable gets the TestItem instance as only argument.
+        """
+        # credit: adapted from Python's unittest.TestCase.run
         #XXX at a later time, this method may accept an object space
         #  as argument
 
+        # prepare result object
+        result = TestResult(self)
+        result.status = None
+
+        # prepare test case class and test method
+        methodname = self.method.__name__
+        testobject = self.cls(methodname)
+        testmethod = getattr(testobject, methodname)
+
+        if pretest is not None:
+            pretest(self)
+        try:
+            try:
+                testobject.setUp()
+            except KeyboardInterrupt:
+                raise
+            except:
+                result._setstatus(ERROR)
+                return
+
+            try:
+                testmethod()
+                result.status = SUCCESS
+            except AssertionError:
+                result._setstatus(FAILURE)
+            except KeyboardInterrupt:
+                raise
+            except:
+                result._setstatus(ERROR)
+
+            try:
+                testobject.tearDown()
+            except KeyboardInterrupt:
+                raise
+            except:
+                result._setstatus(ERROR)
+        finally:
+            if posttest is not None:
+                posttest(self)
+        return result
+
     def __str__(self):
         return "TestItem from %s.%s.%s" % (self.module.__name__,\
                self.cls.__name__, self.method.__name__)
 
     def __repr__(self):
-        return "%s at %#x" % (str(self), id(self))
+        return "<%s at %#x>" % (str(self), id(self))
 
 
 class TestSuite:
@@ -57,20 +119,6 @@
     def __init__(self):
         self.items = []
 
-    def _items_from_module(self, module):
-        """Return a list of TestItems read from the given module."""
-        items = []
-        # scan the module for classes derived from unittest.TestCase
-        for obj in vars(module).values():
-            if inspect.isclass(obj) and issubclass(obj, unittest.TestCase):
-                # we found a TestCase class, now scan it for test methods
-                for obj2 in vars(obj).values():
-                    # ismethod doesn't seem to work here
-                    if inspect.isfunction(obj2) and \
-                      obj2.__name__.startswith("test"):
-                        items.append(TestItem(module, obj, obj2))
-        return items
-
     def _module_from_modpath(self, modpath):
         """
         Return a module object derived from the module path
@@ -85,8 +133,21 @@
         __import__(modpath)
         return sys.modules[modpath]
 
-    def initfromdir(self, dirname, filterfunc=None, recursive=True,
-                    loader=None):
+    def _items_from_module(self, module):
+        """Return a list of TestItems read from the given module."""
+        items = []
+        # scan the module for classes derived from unittest.TestCase
+        for obj in vars(module).values():
+            if inspect.isclass(obj) and issubclass(obj, unittest.TestCase):
+                # we found a TestCase class, now scan it for test methods
+                for obj2 in vars(obj).values():
+                    # inspect.ismethod doesn't seem to work here
+                    if inspect.isfunction(obj2) and \
+                      obj2.__name__.startswith("test"):
+                        items.append(TestItem(module, obj, obj2))
+        return items
+
+    def initfromdir(self, dirname, filterfunc=None, recursive=True):
         """
         Init this suite by reading the directory denoted by dirname,
         then find all test modules in it. Test modules are files that
@@ -96,13 +157,9 @@
         modules by module path. By default, all test modules are used.
 
         If recursive is true, which is the default, find all test modules
-        by scanning the start directory recursively. The argument loader
-        may be set to a test loader class to use. By default, the
-        TestLoader class from the unittest module is used.
+        by scanning the start directory recursively.
         """
         dirname = vpath.getlocal(dirname)
-        if loader is None:
-            loader = unittest.TestLoader()
 
         def testfilefilter(path):
             return path.isfile() and path.fnmatch('test_*.py')
@@ -122,9 +179,27 @@
                 else:
                     self.items.extend(items)
 
+    def testresults(self, results=None):
+        """
+        Return a generator to get the test result for each test item.
+
+        If not None, the argument results must be a list which will
+        receive the result objects for later usage.
+        """
+        for item in self.items:
+            result = item.run()
+            if results is not None:
+                results.append(result)
+            yield result
+
 
 if __name__ == '__main__':
     ts = TestSuite()
     ts.initfromdir(".")
-    print ts.items
+    for res in ts.testresults():
+        print 75 * '-'
+        print "%s: %s" % (res.item, res.status)
+        if res.traceback:
+            print '-----'
+            print res.formatted_traceback
 


More information about the Pypy-commit mailing list