[Zope-Checkins] CVS: Zope3/lib/python/Zope/Testing - Builder.py:1.2 CleanUp.py:1.2 ZODButil.py:1.3 __init__.py:1.6 common.py:1.4 custom_zodb.py:1.3 dispatcher.py:1.5 makerequest.py:1.5
Jim Fulton
jim@zope.com
Mon, 10 Jun 2002 19:30:16 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/Testing
In directory cvs.zope.org:/tmp/cvs-serv20468/lib/python/Zope/Testing
Modified Files:
ZODButil.py __init__.py common.py custom_zodb.py dispatcher.py
makerequest.py
Added Files:
Builder.py CleanUp.py
Log Message:
Merged Zope-3x-branch into newly forked Zope3 CVS Tree.
=== Zope3/lib/python/Zope/Testing/Builder.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+ Utilities for buliding test suites by crawling directories.
+"""
+
+import unittest
+import sys, os
+from fnmatch import fnmatch
+import traceback
+
+global_exceptions = {'Zope.Server.medusa.sendfile.test_sendfile':1,}
+
+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
+
+class TestFinder( unittest.TestLoader ):
+ """
+ Crawl the filesystem, looking for tests.
+ """
+ def __init__( self, root_dir=None ):
+
+ if root_dir is None:
+ root_dir = self._guessSoftwareHome()
+
+ self._root_dir = root_dir
+ self._root_dir_len = len( root_dir.split( os.sep ) )
+ self._candidates = []
+ self._cant_load = []
+ self._maybe_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] )
+ root_dir, rest = os.path.split( zope_pkg )
+ return root_dir
+
+ def _splitPath( self, path ):
+ """
+ Return a list of path elements, relative to root_dir.
+ """
+ return path.split( os.sep )[ self._root_dir_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 _formatException( self, candidate, msg ):
+ """
+ Grab the traceback and store, along with header info.
+ """
+ header = '[%s] %s' % ( candidate, msg )
+ errLines = apply( traceback.format_exception, sys.exc_info() )
+ body = ''.join(errLines)
+ return header, body
+
+ def _recordLoadFailure( self, candidate, msg ):
+ header, body = self._formatException(candidate, msg)
+ self._cant_load.append( ( header, body ) )
+
+ def _deferLoadFailure( self, candidate, msg ):
+ header, body = self._formatException(candidate, msg)
+ self._maybe_cant_load[candidate] = (header, body)
+
+ def _do_import( self, module ):
+ mod = __import__(module)
+ for name in module.split('.')[1:]:
+ mod = getattr(mod, name)
+ return mod
+
+ def _buildSuite( self ):
+ """
+ Build a suite from our candidate modules.
+ """
+ suite = unittest.TestSuite()
+ self._cant_load = []
+ self._loaded = []
+
+ for candidate in self._candidates:
+ if candidate in global_exceptions:
+ continue
+
+ try:
+ mod = self._do_import(candidate)
+ except ImportError:
+ tb = ''.join(traceback.format_exception(*sys.exc_info()))
+ self._cant_load.append(("Failed to import " + candidate, tb))
+ continue
+
+ if hasattr(mod, "test_suite"):
+ suite.addTest(mod.test_suite())
+ continue
+
+ try:
+ suite.addTest(self.loadTestsFromModule(mod))
+ except Exception, msg:
+ if self._maybe_cant_load.get(candidate):
+ self._cant_load.append(self._maybe_cant_load[candidate])
+ self._recordLoadFailure('%s (implicit)' % candidate, msg)
+ else:
+ self._loaded.append( '%s (implicit)' % candidate )
+ return suite
+
+ def _loadTestsFromPath( self, path=None ):
+ if path is None:
+ path = self._root_dir
+ os.path.walk( path, self._visit, None )
+ suite = self._buildSuite()
+ suite.warnings = self._cant_load
+ suite.loaded = self._loaded
+ if suite.warnings:
+ print "There were failures loading tests"
+ print
+ for item in suite.warnings:
+ print item
+ print
+ return suite
+
+ __call__ = _loadTestsFromPath
+
+def allZopeTests():
+ import Zope
+ return TestFinder()( Zope.__path__[0] )
=== Zope3/lib/python/Zope/Testing/CleanUp.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Provide a standard cleanup registry
+
+Unit tests that change global data should include the CleanUp base
+class, which provides simpler setUp and tearDown methods that call
+global-data cleanup routines::
+
+ class Test(CleanUp, unittest.TestCase):
+
+ ....
+
+If custom setUp or tearDown are needed, then the base reoutines should
+be called, as in::
+
+ def tearDown(self):
+ CleanUp.tearDown(self)
+ ....
+
+Cleanup routines for global data should be registered by passing them to
+addCleanup::
+
+ from Zope.Testing.CleanUp import addCleanUp
+ addCleanUp(roleRegistry._clear)
+
+
+Revision information:
+$Id$
+"""
+
+_cleanups = []
+
+def addCleanUp(func, args=(), kw={}):
+ """Register a cleanup routines
+
+ Pass a function to be called to cleanup global data.
+ Optional argument tuple and keyword arguments may be passed.
+ """
+ _cleanups.append((func, args, kw))
+
+def cleanUp(ignored=None):
+ """Clean up global data
+ """
+ for func, args, kw in _cleanups:
+ func(*args, **kw)
+
+class CleanUp:
+ """Mix-in class providing clean-up setUp and tearDown routines
+ """
+ tearDown = setUp = cleanUp
=== Zope3/lib/python/Zope/Testing/ZODButil.py 1.2 => 1.3 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
import os
from glob import glob
import ZODB
=== Zope3/lib/python/Zope/Testing/__init__.py 1.5 => 1.6 ===
#
-# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
@@ -17,17 +18,19 @@
"""
import os
-def pdir(path):
- return os.path.split(path)[0]
-
-# Set the INSTANCE_HOME to the Testing package directory
-os.environ['INSTANCE_HOME'] = INSTANCE_HOME = pdir(__file__)
-
-# Set the SOFTWARE_HOME to the directory containing the Testing package
-os.environ['SOFTWARE_HOME'] = SOFTWARE_HOME = pdir(INSTANCE_HOME)
-
-# Note: we don't set os.environ['ZEO_CLIENT'] anymore because we
-# really do need all the products to be initialized. Some tests
-# use the product registry.
-
+def allZopeTests():
+ from Builder import allZopeTests
+ return allZopeTests()
+
+def patchTracebackModule():
+ """Use the ExceptionFormatter to show more info in tracebacks.
+ """
+ from Zope.Exceptions.ExceptionFormatter import format_exception
+ import traceback
+ traceback.format_exception = format_exception
+
+# Don't use the new exception formatter by default, since it
+# doesn't show filenames.
+if os.environ.get('NEW_ZOPE_EXCEPTION_FORMATTER', 0):
+ patchTracebackModule()
=== Zope3/lib/python/Zope/Testing/common.py 1.3 => 1.4 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+from Types import ClassType
+
# Default test runner
TestRunner = unittest.TextTestRunner
@@ -20,7 +35,6 @@
def test_suite():
# The default test suite includes every subclass of TestCase in
# the module, with 'test' as the test method prefix.
- ClassType = type(unittest.TestCase)
tests = []
for v in globals().values():
if isinstance(v, ClassType) and issubclass(v, unittest.TestCase):
=== Zope3/lib/python/Zope/Testing/custom_zodb.py 1.2 => 1.3 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
import ZODB, os
from ZODB.FileStorage import FileStorage
from ZODB.DemoStorage import DemoStorage
=== Zope3/lib/python/Zope/Testing/dispatcher.py 1.4 => 1.5 ===
#
-# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
#
##############################################################################
+""" Dispatcher for usage inside Zope test environment
-# Dispatcher for usage inside Zope test environment
-# Andreas Jung, andreas@digicool.com 03/24/2001
+Andreas Jung, andreas@digicool.com 03/24/2001
-
-__version__ = '$Id$'
+$Id$
+"""
import os,sys,re,string
@@ -33,7 +34,7 @@
self.f_startup = []
self.f_teardown = []
self.lastlog = ""
- self.lock = threading.Lock()
+ self.lock = threading.Lock()
self.func = func
self.profiling = 0
@@ -74,10 +75,10 @@
mem_watcher.start()
self.start_test = time.time()
- self.name = name
- self.th_data = {}
- self.runtime = {}
- self._threads = []
+ self.name= name
+ self.th_data = {}
+ self.runtime = {}
+ self._threads= []
s2s=self.s2s
@@ -86,11 +87,14 @@
for i in range(0,numthreads):
kw['t_func'] = func
- th = threading.Thread(None,self.worker,name="TH_%s_%03d" % (func,i) ,args=args,kwargs=kw)
+ th = threading.Thread(None,self.worker,
+ name="TH_%s_%03d" % (func,i) ,args=args,kwargs=kw)
self._threads.append(th)
- for th in self._threads: th.start()
- while threading.activeCount() > 1: time.sleep(1)
+ for th in self._threads:
+ th.start()
+ while threading.activeCount() > 1:
+ time.sleep(1)
self.logn('ID: %s ' % self.name)
self.logn('FUNC: %s ' % self.func)
@@ -98,16 +102,22 @@
self.logn('Args: %s' % params)
for th in self._threads:
- self.logn( '%-30s ........................ %9.3f sec' % (th.getName(), self.runtime[th.getName()]) )
+ self.logn( '%-30s ........................ %9.3f sec'
+ % (th.getName(), self.runtime[th.getName()]) )
for k,v in self.th_data[th.getName()].items():
self.logn ('%-30s %-15s = %s' % (' ',k,v) )
self.logn("")
- self.logn('Complete running time: %9.3f sec' % (time.time()-self.start_test) )
+ self.logn(
+ 'Complete running time: %9.3f sec'
+ % (time.time()-self.start_test) )
if len(self.mem_usage)>1: self.mem_usage.remove(-1)
- self.logn( "Memory: start: %s, end: %s, low: %s, high: %s" % \
- (s2s(self.mem_usage[0]),s2s(self.mem_usage[-1]),s2s(min(self.mem_usage)), s2s(max(self.mem_usage))))
+ self.logn( "Memory: start: %s, end: %s, low: %s, high: %s" %
+ (s2s(self.mem_usage[0]),
+ s2s(self.mem_usage[-1]),
+ s2s(min(self.mem_usage)),
+ s2s(max(self.mem_usage))))
self.logn('')
@@ -119,7 +129,7 @@
del kw['t_func']
ts = time.time()
- apply(t_func,args,kw)
+ apply(t_func,args,kw)
te = time.time()
for func in self.f_teardown: getattr(self,func)()
@@ -129,8 +139,7 @@
def th_setup(self):
""" initalize thread with some environment data """
- env = {'start': time.time()
- }
+ env = {'start': time.time()}
return env
@@ -138,15 +147,17 @@
""" famous last actions of thread """
self.lock.acquire()
- self.th_data[ threading.currentThread().getName() ] = kw
- self.runtime [ threading.currentThread().getName() ] = time.time() - env['start']
+ self.th_data[ threading.currentThread().getName() ] = kw
+ self.runtime[ threading.currentThread().getName() ] = ( time.time()
+ - env['start'] )
self.lock.release()
def getmem(self):
""" try to determine the current memory usage """
- if not sys.platform in ['linux2']: return None
+ if not sys.platform in ['linux2']:
+ return None
cmd = '/bin/ps --no-headers -o pid,vsize --pid %s' % os.getpid()
outp = commands.getoutput(cmd)
pid,vsize = filter(lambda x: x!="" , string.split(outp," ") )
@@ -167,7 +178,8 @@
while running ==1:
self.mem_usage.append( self.getmem() )
time.sleep(1)
- if threading.activeCount() == 2: running = 0
+ if threading.activeCount() == 2:
+ running = 0
def register_startup(self,func):
=== Zope3/lib/python/Zope/Testing/makerequest.py 1.4 => 1.5 ===
#
-# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
+# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""