Roll our own unittest framework to add skip support.
authorAlec Warner <antarus@gentoo.org>
Tue, 6 Mar 2007 07:34:18 +0000 (07:34 -0000)
committerAlec Warner <antarus@gentoo.org>
Tue, 6 Mar 2007 07:34:18 +0000 (07:34 -0000)
svn path=/main/trunk/; revision=6181

pym/portage/tests/__init__.py

index 5a69ae3ed4629e33627f8762ee0ba1419fc26390..56fc869c2beabe99d4875b53bbbb6acf9c1cfce8 100644 (file)
@@ -3,19 +3,16 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id$
 
-import os, unittest
+import os, unittest, time
+import portage.tests
 
 def main():
-       
-       testDirs = ["util","versions", "dep"]
-
+       testDirs = ["util","versions", "dep", "xpak"]
        suite = unittest.TestSuite()
-
        basedir = os.path.dirname(__file__)
        for mydir in testDirs:
                suite.addTests(getTests(os.path.join(basedir, mydir), basedir) )
-
-       return unittest.TextTestRunner(verbosity=2).run(suite)
+       return portage.tests.TextTestRunner(verbosity=2).run(suite)
 
 def my_import(name):
        mod = __import__(name)
@@ -49,6 +46,128 @@ def getTests( path, base_path ):
                        raise
        return result
 
+class SkipException(Exception):
+       pass
+
+class TextTestResult(unittest._TextTestResult):
+       """
+       We need a subclass of unittest._TextTestResult to handle skipped
+       tests.
+
+       This just adds an addSkip method that can be used to add
+       skipped tests to the result; these can be displayed later
+       by the test runner.
+       """
+       
+       def __init__( self, stream, descriptions, verbosity ):
+               unittest._TextTestResult.__init__( self, stream, descriptions, verbosity )
+               self.skipped = []
+
+       def addSkip( self, test, info ):
+               self.skipped.append((test,info))
+               if self.showAll:
+                       self.stream.writeln("FAIL AND SKIP")
+               elif self.dots:
+                       self.stream.write(".")
+       
+       def printErrors( self ):
+               if self.dots or self.showAll:
+                       self.stream.writeln()
+                       self.printErrorList('ERROR', self.errors)
+                       self.printErrorList('FAIL', self.failures)
+                       self.printErrorList('SKIP', self.skipped)
+       
+class TestCase(unittest.TestCase):
+       """
+       We need a way to mark a unit test as "ok to fail"
+       This way someone can add a broken test and mark it as failed
+       and then fix the code later.  This may not be a great approach
+       (broken code!!??!11oneone) but it does happen at times.
+       """
+       
+       SkipException = SkipException
+       
+       def __init__(self, methodName='runTest'):
+               # This method exists because unittest.py in python 2.4 stores
+               # the methodName as __testMethodName while 2.5 uses
+               # _testMethodName.
+               self._testMethodName = methodName
+               unittest.TestCase.__init__(self, methodName)
+               
+       def defaultTestResult(self):
+               return TextTestResult()
+
+       def run( self, result=None ):
+               if result is None: result = self.defaultTestResult()
+               result.startTest(self)
+               testMethod = getattr(self, self._testMethodName)
+               try:
+                       try:
+                               self.setUp()
+                       except KeyboardInterrupt:
+                               raise
+                       except:
+                               result.addError(self, self._exc_info())
+                               return
+                       ok = False
+                       try:
+                               testMethod()
+                               ok = True
+                       except self.failureException:
+                               result.addFailure(self, self._exc_info())
+                       except self.SkipException:
+                               result.addSkip(self,"%s: Failed but Skippable" % testMethod)
+                       except KeyboardInterrupt:
+                               raise
+                       except:
+                               result.addError(self, self._exc_info())
+                       try:
+                               self.tearDown()
+                       except KeyboardInterrupt:
+                               raise
+                       except:
+                               result.addError(self, self._exc_info())
+                               ok = False
+                       if ok: result.addSuccess(self)
+               finally:
+                       result.stopTest(self)
+                       
+class TextTestRunner(unittest.TextTestRunner):
+       """
+       We subclass unittest.TextTestRunner to output SKIP for tests that fail but are skippable
+       """
+       
+       def _makeResult(self):
+               return TextTestResult(self.stream, self.descriptions, self.verbosity)
+
+       def run( self, test ):
+               """
+               Run the given test case or test suite.
+               """
+               result = self._makeResult()
+               startTime = time.time()
+               test(result)
+               stopTime = time.time()
+               timeTaken = stopTime - startTime
+               result.printErrors()
+               self.stream.writeln(result.separator2)
+               run = result.testsRun
+               self.stream.writeln("Ran %d test%s in %.3fs" %
+                                                       (run, run != 1 and "s" or "", timeTaken))
+               self.stream.writeln()
+               if not result.wasSuccessful():
+                       self.stream.write("FAILED (")
+                       failed, errored = map(len, (result.failures, result.errors))
+                       if failed:
+                               self.stream.write("failures=%d" % failed)
+                       if errored:
+                               if failed: self.stream.write(", ")
+                               self.stream.write("errors=%d" % errored)
+                       self.stream.writeln(")")
+               else:
+                       self.stream.writeln("OK")
+               return result
+       
 test_cps = ['sys-apps/portage','virtual/portage']
 test_versions = ['1.0', '1.0-r1','2.3_p4','1.0_alpha57']
 test_slots = [ None, '1','gentoo-sources-2.6.17','spankywashere']