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

sschwarzer at codespeak.net sschwarzer at codespeak.net
Fri Dec 19 11:17:42 CET 2003


Author: sschwarzer
Date: Fri Dec 19 11:17:41 2003
New Revision: 2544

Modified:
   pypy/trunk/src/pypy/tool/newtest.py
Log:
Copied unittest.TestCase and started to adapt it for our purposes. This version
doesn't work as expected yet, and will also require changes to the existing
test modules.
Function main: Instead of the parameter skip_selftest reverse logic, away
from double negation, to do_selftest .


Modified: pypy/trunk/src/pypy/tool/newtest.py
==============================================================================
--- pypy/trunk/src/pypy/tool/newtest.py	(original)
+++ pypy/trunk/src/pypy/tool/newtest.py	Fri Dec 19 11:17:41 2003
@@ -4,7 +4,6 @@
 import sys
 import cStringIO as StringIO
 import traceback
-import unittest
 import vpath
 
 #TODO
@@ -12,13 +11,126 @@
 # - support TestItem.run with different object spaces
 # - perhaps we have to be able to compare TestResult and TestItem values
 #   which were pickled (see -c option of current test_all.py)
+# - add docstring to TestItem
+
+#
+# custom TestCase class (adapted from Python's unittest module)
+#
+class TestCase:
+    """A class whose instances are single test cases.
+
+    By default, the test code itself should be placed in a method named
+    'runTest'.
+
+    If the fixture may be used for many test cases, create as
+    many test methods as are needed. When instantiating such a TestCase
+    subclass, specify in the constructor arguments the name of the test method
+    that the instance is to execute.
+
+    Test authors should subclass TestCase for their own tests. Construction
+    and deconstruction of the test's environment ('fixture') can be
+    implemented by overriding the 'setUp' and 'tearDown' methods respectively.
+    """
+    def setUp(self):
+        "Hook method for setting up the test fixture before exercising it."
+        pass
+
+    def tearDown(self):
+        "Hook method for deconstructing the test fixture after testing it."
+        pass
+
+    def fail(self, msg=None):
+        """Fail immediately, with the given message."""
+        raise Failure(msg=msg)
+
+    def failIf(self, expr, msg=None):
+        """Fail the test if the expression is true."""
+        if expr:
+            raise Failure(msg=msg)
+
+    def failUnless(self, expr, msg=None):
+        """Fail the test unless the expression is true."""
+        if not expr:
+            raise Failure(msg=msg)
+
+    def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
+        """
+        Fail unless an exception of class excClass is thrown
+        by callableObj when invoked with arguments args and keyword
+        arguments kwargs. If a different type of exception is
+        thrown, it will not be caught, and the test case will be
+        deemed to have suffered an error, exactly as for an
+        unexpected exception.
+        """
+        try:
+            callableObj(*args, **kwargs)
+        except excClass:
+            return
+        else:
+            if hasattr(excClass,'__name__'):
+                excName = excClass.__name__
+            else:
+                excName = str(excClass)
+            raise Failure(msg=excName)
+
+    def failUnlessEqual(self, first, second, msg=None):
+        """
+        Fail if the two objects are unequal as determined by the '=='
+        operator.
+        """
+        if not first == second:
+            raise Failure(msg=(msg or '%s != %s' % (`first`, `second`)))
+
+    def failIfEqual(self, first, second, msg=None):
+        """
+        Fail if the two objects are equal as determined by the '=='
+        operator.
+        """
+        if first == second:
+            raise Failure(msg=(msg or '%s == %s' % (`first`, `second`)))
+
+    def failUnlessAlmostEqual(self, first, second, places=7, msg=None):
+        """
+        Fail if the two objects are unequal as determined by their
+        difference rounded to the given number of decimal places
+        (default 7) and comparing to zero.
+
+        Note that decimal places (from zero) is usually not the same
+        as significant digits (measured from the most signficant digit).
+        """
+        if round(second-first, places) != 0:
+            raise Failure(msg=(msg or '%s != %s within %s places' %
+                                      (`first`, `second`, `places`)))
+
+    def failIfAlmostEqual(self, first, second, places=7, msg=None):
+        """
+        Fail if the two objects are equal as determined by their
+        difference rounded to the given number of decimal places
+        (default 7) and comparing to zero.
+
+        Note that decimal places (from zero) is usually not the same
+        as significant digits (measured from the most signficant digit).
+        """
+        if round(second-first, places) == 0:
+            raise Failure(msg=(msg or '%s == %s within %s places' %
+                                      (`first`, `second`, `places`)))
+
+    # aliases
+    assertEqual = assertEquals = failUnlessEqual
+    assertNotEqual = assertNotEquals = failIfEqual
+    assertAlmostEqual = assertAlmostEquals = failUnlessAlmostEqual
+    assertNotAlmostEqual = assertNotAlmostEquals = failIfAlmostEqual
+    assertRaises = failUnlessRaises
+    assert_ = failUnless
 
 #
 # TestResult class family
 #
-class TestResult:
+class TestResult(Exception):
     """Abstract class representing the outcome of a test."""
-    def __init__(self, item):
+    def __init__(self, msg="", item=None):
+        Exception.__init__(self, msg)
+        self.msg = msg
         self.item = item
         self.name = self.__class__.__name__
         self.traceback = None
@@ -50,7 +162,7 @@
 
 
 class TestResultWithTraceback(TestResult):
-    def __init__(self, item):
+    def __init__(self, msg='', item=None):
         TestResult.__init__(self, item)
         self.setexception()
 
@@ -139,10 +251,8 @@
 
         # credit: adapted from Python's unittest.TestCase.run
 
-        # prepare test case class and test method
-        methodname = self.method.__name__
-        testobject = self.cls(methodname)
-        testmethod = getattr(testobject, methodname)
+        testobject = self.cls()
+        testmethod = getattr(testobject, self.method.__name__)
 
         if pretest is not None:
             pretest(self)
@@ -153,28 +263,32 @@
                 testobject.setUp()
             except KeyboardInterrupt:
                 raise
-            except:
-                return Error(self)
+            except TestResult, result:
+                # reconstruct TestResult object, implicitly set exception
+                result = result.__class__(msg=result.msg, item=self)
+            except Exception, exc:
+                return Error(msg=str(exc), item=self)
 
             try:
                 testmethod()
-                result = Success(self)
+                result = Success(msg='success', item=self)
             except KeyboardInterrupt:
                 raise
-            except AssertionError:
-                result = Failure(self)
-            except:
-                result = Error(self)
+            except TestResult, result:
+                # reconstruct TestResult object, implicitly set exception
+                result = result.__class__(msg=result.msg, item=self)
+            except Exception, exc:
+                result = Error(msg=str(exc), item=self)
 
             try:
                 testobject.tearDown()
             except KeyboardInterrupt:
                 raise
-            except:
+            except Exception, exc:
                 # if we already had an exception in the test method,
                 # don't overwrite it
-                if not isinstance(result, TestResultWithTraceback):
-                    result = Error(self)
+                if result.traceback is None:
+                    result = Error(msg=str(exc), item=self)
         finally:
             if posttest is not None:
                 posttest(self)
@@ -211,9 +325,11 @@
     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
+        # scan the module for classes derived from TestCase
         for obj in vars(module).values():
-            if inspect.isclass(obj) and issubclass(obj, unittest.TestCase):
+            if inspect.isclass(obj):
+                print obj, id(obj)
+            if inspect.isclass(obj) and isinstance(obj, 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
@@ -234,6 +350,7 @@
         If recursive is true, which is the default, find all test modules
         by scanning the start directory recursively.
         """
+        self.items = []
         dirname = vpath.getlocal(dirname)
 
         def testfilefilter(path):
@@ -270,6 +387,7 @@
         self.lastresults = {}
         for item in self.items:
             result = item.run()
+            print result.formatted_traceback
             key = classify(result)
             self.lastresults.setdefault(key, []).append(result)
             yield result
@@ -277,16 +395,18 @@
 #
 # demonstrate test framework usage
 #
-def main(skip_selftest=True):
+def main(do_selftest=False):
     # possibly ignore dummy unit tests
-    if skip_selftest:
-        filterfunc = lambda m: m.find("pypy.tool.testdata.") == -1
-    else:
+    if do_selftest:
         filterfunc = lambda m: True
+    else:
+        filterfunc = lambda m: m.find("pypy.tool.testdata.") == -1
     # collect tests
     ts = TestSuite()
     print "Loading test modules ..."
     ts.initfromdir(autopath.pypydir, filterfunc=filterfunc)
+    print "Loading test modules ..."
+    ts.initfromdir('.', filterfunc=filterfunc)
     # iterate over tests and collect data
     for res in ts.testresults():
         if res.traceback is None:
@@ -311,4 +431,4 @@
 
 
 if __name__ == '__main__':
-    main()
+    main(do_selftest=True)


More information about the Pypy-commit mailing list