When building unit tests for modules many times using PyUnit feels like overkill. This is a simple implementation for testing single file modules.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | #! /usr/bin/env python
######################################################################
# Written by Kevin L. Sitze on 2010-12-03
# This code may be used pursuant to the MIT License.
######################################################################
import sys
import traceback
from types import FloatType, ComplexType
__all__ = (
'assertEquals',
'assertNotEquals',
'assertException',
'assertFalse',
'assertNone',
'assertNotNone',
'assertSame',
'assertNotSame',
'assertTrue'
)
def colon( msg ):
if msg:
return ": " + str( msg )
else:
return ""
def assertEquals( exp, got, msg = None ):
"""assertEquals( exp, got[, message] )
Two objects test as "equal" if:
* they are the same object as tested by the 'is' operator.
* either object is a float or complex number and the absolute
value of the difference between the two is less than 1e-8.
* applying the equals operator ('==') returns True.
"""
if exp is got:
r = True
elif ( type( exp ) in ( FloatType, ComplexType ) or
type( got ) in ( FloatType, ComplexType ) ):
r = abs( exp - got ) < 1e-8
else:
r = ( exp == got )
if not r:
print >>sys.stderr, "Error: expected <%s> but got <%s>%s" % ( repr( exp ), repr( got ), colon( msg ) )
traceback.print_stack()
def assertNotEquals( exp, got, msg = None ):
"""assertNotEquals( exp, got[, message] )
Two objects test as "equal" if:
* they are the same object as tested by the 'is' operator.
* either object is a float or complex number and the absolute
value of the difference between the two is less than 1e-8.
* applying the equals operator ('==') returns True.
"""
if exp is got:
r = False
elif ( type( exp ) in ( FloatType, ComplexType ) or
type( got ) in ( FloatType, ComplexType ) ):
r = abs( exp - got ) >= 1e-8
else:
r = ( exp != got )
if not r:
print >>sys.stderr, "Error: expected different values but both are equal to <%s>%s" % ( repr( exp ), colon( msg ) )
traceback.print_stack()
def assertException( exceptionType, f, msg = None ):
"""Assert that an exception of type \var{exceptionType}
is thrown when the function \var{f} is evaluated.
"""
try:
f()
except exceptionType:
assert True
else:
print >>sys.stderr, "Error: expected <%s> to be thrown by function%s" % ( exceptionType.__name__, colon( msg ) )
traceback.print_stack()
def assertFalse( b, msg = None ):
"""assertFalse( b[, message] )
"""
if b:
print >>sys.stderr, "Error: expected value to be False%s" % colon( msg )
traceback.print_stack()
def assertNone( x, msg = None ):
assertSame( None, x, msg )
def assertNotNone( x, msg = None ):
assertNotSame( None, x, msg )
def assertSame( exp, got, msg = None ):
if got is not exp:
print >>sys.stderr, "Error: expected <%s> to be the same object as <%s>%s" % ( repr( exp ), repr( got ), colon( msg ) )
traceback.print_stack()
def assertNotSame( exp, got, msg = None ):
if got is exp:
print >>sys.stderr, "Error: expected two distinct objects but both are the same object <%s>%s" % ( repr( exp ), colon( msg ) )
traceback.print_stack()
def assertTrue( b, msg = None ):
if not b:
print >>sys.stderr, "Error: expected value to be True%s" % colon( msg )
traceback.print_stack()
if __name__ == "__main__":
assertNone( None )
assertEquals( 5, 5 )
assertException( KeyError, lambda: {}['test'] )
assertNone( 5, 'this assertion is expected' )
assertEquals( 5, 6, 'this assertion is expected' )
assertException( KeyError, lambda: {}, 'this assertion is expected' )
|
You may have noticed in some of my other recipes that I commonly place unit tests for the module at the bottom of the file. Those tests originally used this code, however I simply cut and pasted the appropriate "assert" functions out of this file into those recipes to help them be more self-contained.
This is how the original code looked:
if __name__ == '__main__':
from assertions import *
assertEquals( ... )
...
This is how your modules also can look.
I despise how heavy-handed PyUnit is when working with a single file. Having these functions outside of a class and stand-alone helps immensely when building single purpose library modules.
My hope is that making writing tests simpler will encourage more recipe authors to add tests to their code.
Download
Copy to clipboard