[Zope-Checkins] CVS: Zope3/lib/python/Zope/Testing - Builder.py:1.1.4.1
Tres Seaver
tseaver@zope.com
Mon, 19 Nov 2001 19:26:17 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/Testing
In directory cvs.zope.org:/tmp/cvs-serv8568/lib/python/Zope/Testing
Added Files:
Tag: Zope-3x-branch
Builder.py
Log Message:
- Integrate test-crawler, to enable better use of 'unittestgui.py'.
=== Added File Zope3/lib/python/Zope/Testing/Builder.py ===
"""
Utilities for buliding test suites by crawling directories.
"""
import unittest
import sys, os, string, re
from fnmatch import fnmatch
import imp, traceback
def getSuiteFromFile( filepath ):
"""
Extract and return the test suite from filepath.
"""
if not os.path.isfile(filepath):
raise ValueError, '%s is not a file' % filepath
path, filename = os.path.split(filepath)
name, ext = os.path.splitext(filename)
file, pathname, desc = imp.find_module( name, [ path ] )
saved_syspath = sys.path[:]
try:
module=imp.load_module( name, file, pathname, desc )
finally:
file.close()
sys.path[:] = saved_syspath
function=getattr( module, 'test_suite', None )
if function is None:
return None
return function()
TEST_FILE_NAME = re.compile( r'^test([A-Za-z0-9_]+).py$' )
TEST_SUITE_DEF = re.compile( r'^def test_suite\(' )
def smellsLikeATest( filepath
):
"""
Does 'filepath' match our criteria for unit test modules?
- filename matches 'test*.py';
- defines a 'test_suite' function at module scope.
"""
path, name = os.path.split( filepath )
fname, ext = os.path.splitext( name )
match = TEST_FILE_NAME.match( name )
if match and match.group(0) != 'runner':
return len( filter( TEST_SUITE_DEF.match
, open( filepath, 'r' ).readlines() ) ) > 0
return 0
def listTestableNames( pathname ):
"""
Return a list of the names to be traversed to build tests.
"""
names = os.listdir( pathname )
if '.testinfo' in names: # allow local control
f = open( os.path.join( pathname, '.testinfo' ) )
lines = filter( None, f.readlines() )
f.close()
lines = map( lambda x: # remove trailing newlines
x[-1]=='\n' and x[:-1] or x
, lines )
names = filter( lambda x: # skip comments
x and x[0] != '#'
, lines )
return names
def extractSuite( pathname ):
"""
Extract and return the appropriate test suite, along with
a list of filed imports.
"""
suite = None
import_failures = []
if os.path.isdir( pathname ):
suite = unittest.TestSuite()
for name in listTestableNames( pathname ):
fullpath = os.path.join( pathname, name )
sub_suite, sub_failures = extractSuite( fullpath )
if sub_suite:
suite.addTest( sub_suite )
import_failures.extend( sub_failures )
if not suite.countTestCases(): # ignore empty suites
suite = None
elif smellsLikeATest( pathname ):
working_dir = os.getcwd()
try:
dirname, name = os.path.split( pathname )
if dirname:
os.chdir( dirname )
try:
suite = getSuiteFromFile( name )
except:
import_failures.append( pathname )
finally:
os.chdir( working_dir )
return suite, import_failures
class TestFinder( unittest.TestLoader ):
"""
Handle crawling the filesystem, looking for tests.
"""
def __init__( self, sw_home=None ):
if sw_home is None:
sw_home = self._guessSoftwareHome()
self._sw_home = sw_home
self._sw_home_len = len( sw_home.split( os.sep ) )
self._candiates = []
self._cant_load = []
def _guessSoftwareHome( self ):
"""
Attempt to guess where SOFTWARE_HOME is.
"""
from Zope import Testing
zope_pkg, rest = os.path.split( Testing.__path__[0] )
sw_home, rest = os.path.split( zope_pkg )
return sw_home
def _splitPath( self, path ):
"""
Return a list of path elements, relative to sw_home.
"""
return path.split( os.sep )[ self._sw_home_len : ]
def _visit( self, arg, dirname, names ):
"""
Visitor for os.path.walk.
"""
names[:] = listTestableNames( dirname )
for name in names:
if fnmatch( name, 'test*.py' ) and name != 'testrunner.py':
self._addCandidate( dirname, name )
def _addCandidate( self, dirname, name ):
"""
Append a candidate module path.
"""
elements = self._splitPath( dirname )
basename, ext = os.path.splitext( name )
elements.append( basename )
self._candidates.append( '.'.join( elements ) )
def _buildSuite( self ):
"""
Build a suite from our candidate modules.
"""
suite = unittest.TestSuite()
self._cant_load = []
loaded = []
for candidate in self._candidates:
try:
suite.addTest( self.loadTestsFromName( '%s.test_suite'
% candidate ) )
loaded.append( '%s (test_suite)' % candidate )
except ValueError:
try:
suite.addTest( self.loadTestsFromName( candidate ) )
append( '%s (implicit)' % candidate )
except ValueError, msg:
self._cant_load.append( '[%s] %s' % ( candidate, msg ) )
except Exception, msg:
self._cant_load.append( '[%s] %s' % ( candidate, msg ) )
return suite, loaded
def loadTestsFromPath( self, path=None ):
self._candidates = []
self._cant_load = []
if path is None:
path = self._sw_home
os.path.walk( path, self._visit, None )
suite, loaded = self._buildSuite()
return suite
def allZopeTests():
#suite, failed_imports = extractSuite( sw_home )
#return suite
return TestFinder().loadTestsFromPath()