[Zope-Checkins] SVN: Zope/trunk/utilities/testrunner.py removed
Andreas Jung
andreas at andreas-jung.com
Sat May 15 13:58:52 EDT 2004
Log message for revision 24720:
removed
-=-
Deleted: Zope/trunk/utilities/testrunner.py
===================================================================
--- Zope/trunk/utilities/testrunner.py 2004-05-15 16:39:22 UTC (rev 24719)
+++ Zope/trunk/utilities/testrunner.py 2004-05-15 17:58:51 UTC (rev 24720)
@@ -1,534 +0,0 @@
-#!/usr/bin/env python2.3
-
-"""testrunner - a Zope test suite utility.
-
-The testrunner utility is used to execute PyUnit test suites. This utility
-should be run from the root of your Zope source directory. It will set up the
-correct python path environment based on your source directory so that
-test suites can import Zope modules in a way that is fairly independent of
-the location of the test suite. It does *not* import the Zope package, so
-a test thats depend on dynamic aspects of the Zope environment (such as
-SOFTWARE_HOME being defined) may need to 'import Zope' as a part of the
-test suite.
-
-Testrunner will look for and execute test suites that follow some simple
-conventions. Test modules should have a name prefixed with 'test', such as
-'testMyModule.py', and test modules are expected to define a module function
-named 'test_suite' that returns a TestSuite object. By convention,
-we put test modules in a 'tests' sub-package of the package they test.
-
-Testrunner is used to run all checked in test suites before (final) releases
-are made, and can be used to quickly run a particular suite or all suites in
-a particular directory."""
-
-import getopt
-import imp
-import os
-import sys
-import time
-import traceback
-import unittest
-
-VERBOSE = 2
-
-class TestRunner:
- """Test suite runner"""
-
- def __init__(self, path, verbosity, mega_suite, verbose_on_error):
- self.basepath = path
- self.verbosity = verbosity
- self.verbose_on_error = verbose_on_error
- self.results = []
- self.mega_suite = mega_suite
- # initialize python path
- pjoin = os.path.join
- if sys.platform == 'win32':
- newpaths = [pjoin(path, 'lib', 'python'),
- pjoin(path, 'bin', 'lib'),
- pjoin(path, 'bin', 'lib', 'plat-win'),
- pjoin(path, 'bin', 'lib', 'win32'),
- pjoin(path, 'bin', 'lib', 'win32', 'lib'),
- path]
- else:
- newpaths = [pjoin(path, 'lib', 'python'),
- path]
- sys.path[:0] = newpaths
-
- def getSuiteFromFile(self, 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[:]
- module = None
- try:
- sys.path.append(path) # let module find things in its dir
- try:
- module=imp.load_module(name, file, pathname, desc)
- except KeyboardInterrupt:
- raise
- except:
- (tb_t, tb_v, tb_tb) = sys.exc_info()
- self.report("Module %s failed to load\n%s: %s" % (pathname,
- tb_t, tb_v))
- self.report(''.join(traceback.format_tb(tb_tb)) + '\n')
- del tb_tb
- finally:
- file.close()
- sys.path.pop() # Remove module level path
- sys.path[:] = saved_syspath
- function=getattr(module, 'test_suite', None)
- if function is None:
- return None
- return function()
-
- def smellsLikeATest(self, filepath):
- path, name = os.path.split(filepath)
- fname, ext = os.path.splitext(name)
-
- if ( name[:4] == 'test'
- and name[-3:] == '.py'
- and name != 'testrunner.py'):
- file = open(filepath, 'r')
- lines = file.readlines()
- file.close()
- for line in lines:
- if (line.find('def test_suite(') > -1) or \
- (line.find('framework(') > -1):
- return True
- return False
-
- def runSuite(self, suite):
- if suite:
- runner = self.getTestRunner()
- self.results.append(runner.run(suite))
- else:
- self.report('No suitable tests found')
-
- _runner = None
-
- def getTestRunner(self):
- if self._runner is None:
- self._runner = self.createTestRunner()
- return self._runner
-
- def createTestRunner(self):
- return FancyTestRunner(stream=sys.stderr,
- verbosity=self.verbosity,
- verbose_on_error=self.verbose_on_error)
-
- def report(self, message):
- print >>sys.stderr, message
-
- def runAllTests(self):
- """Run all tests found in the current working directory and
- all subdirectories."""
- self.runPath(self.basepath)
-
- def listTestableNames(self, pathname):
- """Return a list of the names to be traversed to build tests."""
- names = os.listdir(pathname)
- for ignore in ('build', 'build-base'):
- if ignore in names:
- # Don't recurse into build directories created by setup.py
- names.remove(ignore)
- if '.testinfo' in names: # allow local control
- f = open(os.path.join(pathname, '.testinfo'))
- lines = filter(None, f.readlines())
- lines = map(lambda x: x[-1]=='\n' and x[:-1] or x, lines)
- names = filter(lambda x: x and x[0] != '#', lines)
- f.close()
- return names
-
- def extractSuite(self, pathname):
- """Extract and return the appropriate test suite."""
- if os.path.isdir(pathname):
- suite = unittest.TestSuite()
- for name in self.listTestableNames(pathname):
- fullpath = os.path.join(pathname, name)
- sub_suite = self.extractSuite(fullpath)
- if sub_suite:
- suite.addTest(sub_suite)
- return suite.countTestCases() and suite or None
-
- elif self.smellsLikeATest(pathname):
- dirname, name = os.path.split(pathname)
- working_dir = os.getcwd()
- try:
- if dirname:
- os.chdir(dirname)
- try:
- suite = self.getSuiteFromFile(name)
- except KeyboardInterrupt:
- raise
- except:
- self.report('No test suite found in file:\n%s\n'
- % pathname)
- if self.verbosity > 1:
- traceback.print_exc()
- suite = None
- finally:
- os.chdir(working_dir)
- return suite
-
- else:
- # no test there!
- return None
-
- def runPath(self, pathname):
- """Run all tests found in the directory named by pathname
- and all subdirectories."""
- if not os.path.isabs(pathname):
- pathname = os.path.join(self.basepath, pathname)
-
- if self.mega_suite:
- suite = self.extractSuite(pathname)
- self.runSuite(suite)
- else:
- for name in self.listTestableNames(pathname):
- fullpath = os.path.join(pathname, name)
- if os.path.isdir(fullpath):
- self.runPath(fullpath)
- elif self.smellsLikeATest(fullpath):
- self.runFile(fullpath)
-
- def runFile(self, filename):
- """Run the test suite defined by filename."""
- working_dir = os.getcwd()
- dirname, name = os.path.split(filename)
- if dirname:
- if self.verbosity > 2:
- print >>sys.stderr, '*** Changing directory to:', dirname
- os.chdir(dirname)
- self.report('Running: %s' % filename)
- try:
- suite = self.getSuiteFromFile(name)
- except KeyboardInterrupt:
- raise
- except:
- traceback.print_exc()
- suite = None
- if suite is not None:
- self.runSuite(suite)
- else:
- self.report('No test suite found in file:\n%s\n' % filename)
- if self.verbosity > 2:
- print >>sys.stderr, '*** Restoring directory to:', working_dir
- os.chdir(working_dir)
-
-
-class FancyTestResult(unittest._TextTestResult):
- have_blank_line = 1
- verbose_on_error = 0
-
- def __init__(self, *args, **kw):
- if "verbose_on_error" in kw:
- self.verbose_on_error = kw["verbose_on_error"]
- del kw["verbose_on_error"]
- unittest._TextTestResult.__init__(self, *args, **kw)
-
- def addSuccess(self, test):
- unittest.TestResult.addSuccess(self, test)
- if self.showAll:
- self.stream.writeln("ok")
- elif self.dots:
- self.stream.write('.')
- self.have_blank_line = 0
-
- def addError(self, test, err):
- unittest.TestResult.addError(self, test, err)
- if self.showAll:
- if isinstance(err[0], str):
- self.stream.writeln(err[0])
- else:
- self.stream.writeln(excname(err[0]))
- elif self.verbose_on_error:
- if not self.have_blank_line:
- self.stream.writeln()
- self.stream.write(self.getDescription(test) + ": ")
- if isinstance(err[0], str):
- self.stream.writeln(err[0])
- else:
- self.stream.writeln(excname(err[0]))
- self.have_blank_line = 1
- elif self.dots:
- self.stream.write("E")
- self.have_blank_line = 0
-
- def addFailure(self, test, err):
- unittest.TestResult.addFailure(self, test, err)
- if self.showAll:
- self.stream.writeln("FAIL")
- elif self.verbose_on_error:
- if not self.have_blank_line:
- self.stream.writeln()
- self.stream.writeln(self.getDescription(test) + ": FAIL")
- self.have_blank_line = 1
- elif self.dots:
- self.stream.write("F")
- self.have_blank_line = 0
-
-def excname(cls):
- if cls.__module__ == "exceptions":
- return cls.__name__
- else:
- return "%s.%s" % (cls.__module__, cls.__name__)
-
-
-class FancyTestRunner(unittest.TextTestRunner):
- def __init__(self, *args, **kw):
- if "verbose_on_error" in kw:
- self.verbose_on_error = kw["verbose_on_error"]
- del kw["verbose_on_error"]
- else:
- self.verbose_on_error = False
- unittest.TextTestRunner.__init__(self, *args, **kw)
-
- def _makeResult(self):
- return FancyTestResult(self.stream, self.descriptions, self.verbosity,
- verbose_on_error=self.verbose_on_error)
-
-
-class TimingTestResult(FancyTestResult):
- def __init__(self, *args, **kw):
- self.timings = []
- FancyTestResult.__init__(self, *args, **kw)
-
- def startTest(self, test):
- FancyTestResult.startTest(self, test)
- self._t2 = None
- self._t1 = time.time()
-
- def stopTest(self, test):
- t2 = time.time()
- if self._t2 is not None:
- t2 = self._t2
- t = t2 - self._t1
- self.timings.append((t, str(test)))
- FancyTestResult.stopTest(self, test)
-
- def addSuccess(self, test):
- self._t2 = time.time()
- FancyTestResult.addSuccess(self, test)
-
- def addError(self, test, err):
- self._t2 = time.time()
- FancyTestResult.addError(self, test, err)
-
- def addFailure(self, test, err):
- self._t2 = time.time()
- FancyTestResult.addFailure(self, test, err)
-
-
-class TimingTestRunner(FancyTestRunner):
- def __init__(self, *args, **kw):
- FancyTestRunner.__init__(self, *args, **kw)
- self.timings = []
-
- def _makeResult(self):
- r = TimingTestResult(self.stream, self.descriptions, self.verbosity,
- verbose_on_error=self.verbose_on_error)
- self.timings = r.timings
- return r
-
-
-class TestTimer(TestRunner):
- def createTestRunner(self):
- return TimingTestRunner(stream=sys.stderr,
- verbosity=self.verbosity,
- verbose_on_error=self.verbose_on_error)
-
- def reportTimes(self, num):
- r = self.getTestRunner()
- r.timings.sort()
- for item in r.timings[-num:]:
- print "%.1f %s" % item
-
-
-def remove_stale_bytecode(arg, dirname, names):
- names = map(os.path.normcase, names)
- for name in names:
- if name.endswith(".pyc") or name.endswith(".pyo"):
- srcname = name[:-1]
- if srcname not in names:
- fullname = os.path.join(dirname, name)
- print "Removing stale bytecode file", fullname
- os.unlink(fullname)
-
-def main(args):
- usage_msg = """Usage: python testrunner.py options
-
- If run without options, testrunner will display this usage
- message. If you want to run all test suites found in all
- subdirectories of the current working directory, use the
- -a option.
-
- options:
-
- -a
- Run all tests found in all subdirectories of the current
- working directory.
-
- -m
- Run all tests in a single, giant suite (consolidates error
- reporting). [default]
-
- -M
- Run each test file's suite separately (noisier output, may
- help in isolating global effects later).
-
- -p
- Add 'lib/python' to the Python search path. [default]
-
- -P
- *Don't* add 'lib/python' to the Python search path.
-
- -d dirpath
- Run all tests found in the directory specified by dirpath,
- and recursively in all its subdirectories. The dirpath
- should be a full system path.
-
- -f filepath
- Run the test suite found in the file specified. The filepath
- should be a fully qualified path to the file to be run.
-
- -v level
- Set the Verbosity level to level. Newer versions of
- unittest.py allow more options than older ones. Allowed
- values are:
-
- 0 - Silent
- 1 - Quiet (produces a dot for each succesful test)
- 2 - Verbose (default - produces a line of output for each test)
-
- -e
- Modifier to the verbosity level. This causes a errors and
- failures to generate a one-line report the test instead of
- an 'E' or 'F'. This can make it easier to work on solving
- problem while the tests are still running. This causes the
- 'silent' mode (-v0) to be less than completely silent.
-
- -q
- Run tests without producing verbose output. The tests are
- normally run in verbose mode, which produces a line of
- output for each test that includes the name of the test and
- whether it succeeded. Running with -q is the same as
- running with -v1.
-
- -o filename
- Output test results to the specified file rather than
- to stderr.
-
- -t N
- Report time taken by the most expensive N tests.
-
- -h
- Display usage information.
- """
-
- pathname = None
- filename = None
- test_all = False
- verbosity = VERBOSE
- mega_suite = True
- set_python_path = True
- timed = 0
- verbose_on_error = False
-
- options, arg = getopt.getopt(args, 'aemPhd:f:v:qMo:t:')
- if not options:
- err_exit(usage_msg)
- for name, value in options:
- if name == '-a':
- test_all = True
- elif name == '-m':
- mega_suite = True
- elif name == '-M':
- mega_suite = False
- elif name == '-p':
- set_python_path = True
- elif name == '-P':
- set_python_path = False
- elif name == '-d':
- pathname = value.strip()
- elif name == '-f':
- filename = value.strip()
- elif name == '-h':
- err_exit(usage_msg, 0)
- elif name == '-e':
- verbose_on_error = True
- elif name == '-v':
- verbosity = int(value)
- elif name == '-q':
- verbosity = 1
- elif name == '-t':
- timed = int(value)
- assert timed >= 0
- elif name == '-o':
- f = open(value, 'w')
- sys.stderr = f
- else:
- err_exit(usage_msg)
-
- os.path.walk(os.curdir, remove_stale_bytecode, None)
-
- if timed:
- testrunner = TestTimer(os.getcwd(), verbosity, mega_suite,
- verbose_on_error)
- else:
- testrunner = TestRunner(os.getcwd(), verbosity, mega_suite,
- verbose_on_error)
-
- if set_python_path:
- script = sys.argv[0]
- script_dir = os.path.dirname(os.path.abspath(script))
- zope_dir = os.path.dirname(script_dir)
- sw_home = os.path.join(zope_dir, 'lib', 'python')
- if verbosity > 1:
- testrunner.report("Adding %s to sys.path." % sw_home)
- sys.path.insert(0, sw_home)
- os.environ['SOFTWARE_HOME'] = sw_home
-
- try:
- # Try to set up the testing environment (esp. INSTANCE_HOME,
- # so we use the right custom_zodb.py.)
- import Testing
- except ImportError:
- pass
-
- if test_all:
- testrunner.runAllTests()
- elif pathname:
- testrunner.runPath(pathname)
- elif filename:
- testrunner.runFile(filename)
-
- if timed:
- testrunner.reportTimes(timed)
-
- ## Report overall errors / failures if there were any
- fails = reduce(lambda x, y: x + len(y.failures), testrunner.results, 0)
- errs = reduce(lambda x, y: x + len(y.errors), testrunner.results, 0)
- if fails or errs:
- msg = '=' * 70
- msg += "\nOVERALL FAILED ("
- if fails:
- msg += "total failures=%d" % fails
- if errs:
- if fails:
- msg += ", "
- msg += "total errors=%d" % errs
- msg += ")"
- err_exit(msg, 1)
-
- sys.exit(0)
-
-
-def err_exit(message, rc=2):
- sys.stderr.write("\n%s\n" % message)
- sys.exit(rc)
-
-
-if __name__ == '__main__':
- main(sys.argv[1:])
More information about the Zope-Checkins
mailing list