################################################################################ # Copyright (c) 1999,2000 Tres Seaver, Palladion Software # ------------------------------------------------------- # # LICENSE # # Permission to reproduce and create derivative works from the # Software ("Software Derivative Works") is hereby granted to you # under the copyright of Tres Seaver (the Author). The Author also grants # you the right to distribute the Software and Software Derivative Works. # # The Author licenses the Software to you on an "AS IS" basis, without # warranty of any kind. THE AUTHOR HEREBY EXPRESSLY DISCLAIMS ALL # WARRANTIES OR CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT # NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF # MERCHANTABILITY, NON INFRINGEMENT AND FITNESS FOR A PARTICULAR # PURPOSE. You are solely responsible for determining the # appropriateness of using the Software and assume all risks # associated with the use and distribution of this Software, including # but not limited to the risks of program errors, damage to or loss of # data, programs or equipment, and unavailability or interruption of # operations. THE AUTHOR WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES # OR FOR ANY SPECIAL, INCIDENTAL, OR INDIRECT DAMAGES OR FOR ANY # ECONOMIC CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS), # EVEN IF THE AUTHOR HAD BEEN ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. The Author will not be liable for the loss of, or damage # to, your records or data, or any damages claimed by you based on a # third party claim. # # You agree to distribute the Software and any Software Derivatives # under a license agreement that: 1) is sufficient to notify all # licensees of the Software and Software Derivatives that the Author # assumes no liability for any claim that may arise regarding the # Software or Software Derivatives, and 2) that disclaims all # warranties, both express and implied, from the Author regarding the # Software and Software Derivatives. (If you include this Agreement # with any distribution of the Software and Software Derivatives you # will have meet this requirement). You agree that you will not # delete any copyright notices in the Software. # # This Agreement is the exclusive statement of your rights in the # Software as provided by the Author. Except for the licenses # granted to you in the second paragraph above, no other licenses are # granted hereunder, by estoppel, implication or otherwise. ################################################################################ __doc__ = """ Emulate JUnit testing framework.""" __version__="1.0" import sys import string import types #------------------------------------------------------------------------------- def abstractMethodCalled(): raise Exception( "abstract method called" ) #------------------------------------------------------------------------------- def assertValue( got, expected, msg ): """ """ assert expected == got, '%s: expected %s, got %s' % ( msg, expected, got ) #------------------------------------------------------------------------------- def assertValueDelta( got, expected, delta, msg ): """ """ assert abs( expected - got ) <= delta, \ '%s: expected %s, got %s, delta %s' % ( msg, expected, got, delta ) #------------------------------------------------------------------------------- class TestResults: """ """ def __init__( self ): self.testsRun = 0 self.failures = [] self.errors = [] def run( self, testCase ): try: self.testsRun = self.testsRun + 1 testCase.fctn() except AssertionError, ae: self.failures.append( ( testCase.name, ae ) ) except Exception, e: self.errors.append( ( testCase.name, e ) ) except: self.errors.append( ( testCase.name, 'non-Exception object' ) ) def __str__( self ): lines = [] if self.failures or self.errors: for failure in self.failures: lines.append( '[%-30s] failed: %s' % failure ) for error in self.errors: lines.append( '[%-30s] threw: %s' % error ) else: lines.append( 'OK' ) return string.join( lines, '\n' ) #------------------------------------------------------------------------------- class TestCase: """ """ def __init__( self, name, fctn ): self.name = name self.fctn = fctn def __call__( self, result ): result.run( self ) return result #------------------------------------------------------------------------------- class TestSuite: """ """ def __init__( self, name ): self.name = name self.children = [] def addChild( self, child ): self.children.append( child ) def __call__( self, result ): for child in self.children: child( result ) return result #------------------------------------------------------------------------------- def suiteFromDict( namespace ): suite = TestSuite( namespace[ '__name__' ] ) for key, value in namespace.items(): if key[:4] == 'test' and type( value ) == types.FunctionType: suite.addChild( TestCase( key[ 4: ], value ) ) return suite #------------------------------------------------------------------------------- def buildTestSuite( target ): if type( target ) == types.DictionaryType: return suiteFromDict( target ) elif type( target ) == types.ModuleType: return buildTestSuite( target.__dict__ ) elif type( target ) == types.StringType: if globals().has_key( target ): target = globals()[ target ] else: target = __import__( target, globals() ) return buildTestSuite( target ) elif type( target ) == types.ListType or type( target ) == types.TupleType: suite = TestSuite( '' ) for element in target: suite.addChild( buildTestSuite( element ) ) return suite #------------------------------------------------------------------------------- def runUnitTests( target ): suite = buildTestSuite( target ) results = TestResults() return suite( results ) #------------------------------------------------------------------------------- def exerciseUnitTests(): def doFine(): pass def doFail(): assert 0, 'asserted 0' def doExcept(): raise Exception( 'Except' ) def doPuke(): raise 'Puke' secondary = { '__name__' : 'Secondary namespace' , 'testFineXX' : doFine , 'testFailXX' : doFail , 'testExceptXX' : doExcept , 'testPukeXX' : doPuke } suite = buildTestSuite( secondary ) results = TestResults() suite( results ) print 'Expecting one fail and two throws:' print str( results ) assert len( results.failures ) == 1 assert len( results.errors ) == 2 #------------------------------------------------------------------------------- if __name__ == '__main__': testUnitTests = exerciseUnitTests results = runUnitTests( globals() ) print str( results )