[Zope-Checkins] CVS: Zope - test.py:1.2.2.3
Stefan H. Holek
stefan at epy.co.at
Thu Mar 25 17:27:19 EST 2004
Update of /cvs-repository/Zope
In directory cvs.zope.org:/tmp/cvs-serv21055
Modified Files:
Tag: Zope-2_7-branch
test.py
Log Message:
Synced changes from HEAD to 2_7-branch.
=== Zope/test.py 1.2.2.2 => 1.2.2.3 ===
--- Zope/test.py:1.2.2.2 Thu Mar 18 08:24:01 2004
+++ Zope/test.py Thu Mar 25 17:27:17 2004
@@ -16,13 +16,28 @@
"""
test.py [-abcdDfgGhLmprtTuv] [modfilter [testfilter]]
-Test harness.
+Find and run tests written using the unittest module.
+
+The test runner searches for Python modules that contain test suites.
+It collects those suites, and runs the tests. There are many options
+for controlling how the tests are run. There are options for using
+the debugger, reporting code coverage, and checking for refcount problems.
+
+The test runner uses the following rules for finding tests to run. It
+searches for packages and modules that contain "tests" as a component
+of the name, e.g. "frob.tests.nitz" matches this rule because tests is
+a sub-package of frob. Within each "tests" package, it looks for
+modules that begin with the name "test." For each test module, it
+imports the module and calls the test_suite() method, which must
+return a unittest TestSuite object. (If a package contains a file
+named .testinfo, it will not be searched for tests. Really.)
-a level
--all
- Run the tests at the given level. Any test at a level at or below this is
- run, any test at a level above this is not run. Level 0 runs all tests.
- The default is to run tests at level 1. --all is a shortcut for -a 0.
+ Run the tests at the given level. Any test at a level at or below
+ this is run, any test at a level above this is not run. Level 0
+ runs all tests. The default is to run tests at level 1. --all is
+ a shortcut for -a 0.
-b
Run "python setup.py build_ext -i" before running tests, where
@@ -54,10 +69,10 @@
Run functional tests instead of unit tests.
-g threshold
- Set the garbage collector generation0 threshold. This can be used to
- stress memory and gc correctness. Some crashes are only reproducible when
- the threshold is set to 1 (agressive garbage collection). Do "-g 0" to
- disable garbage collection altogether.
+ Set the garbage collector generation0 threshold. This can be used
+ to stress memory and gc correctness. Some crashes are only
+ reproducible when the threshold is set to 1 (agressive garbage
+ collection). Do "-g 0" to disable garbage collection altogether.
-G gc_option
Set the garbage collection debugging flags. The argument must be one
@@ -88,26 +103,26 @@
This requires that Python was built --with-pydebug.
-T
- Use the trace module from Python for code coverage. XXX This only works
- if trace.py is explicitly added to PYTHONPATH. The current utility writes
- coverage files to a directory named `coverage' that is parallel to
- `build'. It also prints a summary to stdout.
+ Use the trace module from Python for code coverage. XXX This only
+ works if trace.py is explicitly added to PYTHONPATH. The current
+ utility writes coverage files to a directory named `coverage' that
+ is parallel to `build'. It also prints a summary to stdout.
-v
- Verbose output. With one -v, unittest prints a dot (".") for each test
- run. With -vv, unittest prints the name of each test (for some definition
- of "name" ...). With no -v, unittest is silent until the end of the run,
- except when errors occur.
+ Verbose output. With one -v, unittest prints a dot (".") for each
+ test run. With -vv, unittest prints the name of each test (for
+ some definition of "name" ...). With no -v, unittest is silent
+ until the end of the run, except when errors occur.
-u
-m
- Use the PyUnit GUI instead of output to the command line. The GUI imports
- tests on its own, taking care to reload all dependencies on each run. The
- debug (-d), verbose (-v), and Loop (-L) options will be ignored. The
- testfilter filter is also not applied.
+ Use the PyUnit GUI instead of output to the command line. The GUI
+ imports tests on its own, taking care to reload all dependencies
+ on each run. The debug (-d), verbose (-v), and Loop (-L) options
+ will be ignored. The testfilter filter is also not applied.
- -m starts the gui minimized. Double-clicking the progress bar will start
- the import and run all tests.
+ -m starts the gui minimized. Double-clicking the progress bar
+ will start the import and run all tests.
modfilter
@@ -183,7 +198,7 @@
self._debug = debug
self._progress = progress
self._progressWithNames = False
- self._count = count
+ self.count = count
self._testtimes = {}
if progress and verbosity == 1:
self.dots = False
@@ -240,9 +255,9 @@
def startTest(self, test):
if self._progress:
self.stream.write("\r%4d" % (self.testsRun + 1))
- if self._count:
- self.stream.write("/%d (%5.1f%%)" % (self._count,
- (self.testsRun + 1) * 100.0 / self._count))
+ if self.count:
+ self.stream.write("/%d (%5.1f%%)" % (self.count,
+ (self.testsRun + 1) * 100.0 / self.count))
if self.showAll:
self.stream.write(": ")
elif self._progressWithNames:
@@ -315,14 +330,20 @@
self.__super_init(**kwarg)
self._debug = debug
self._progress = progress
+ # Create the test result here, so that we can add errors if
+ # the test suite search process has problems. The count
+ # attribute must be set in run(), because we won't know the
+ # count until all test suites have been found.
+ self.result = ImmediateTestResult(
+ self.stream, self.descriptions, self.verbosity, debug=self._debug,
+ progress=self._progress)
def _makeResult(self):
- return ImmediateTestResult(self.stream, self.descriptions,
- self.verbosity, debug=self._debug,
- count=self._count, progress=self._progress)
+ # Needed base class run method.
+ return self.result
def run(self, test):
- self._count = test.countTestCases()
+ self.result.count = test.countTestCases()
return unittest.TextTestRunner.run(self, test)
# setup list of directories to put on the path
@@ -392,6 +413,12 @@
def visit(self, rx, dir, files):
if os.path.split(dir)[1] != self.dirname:
+ # Allow tests module rather than package.
+ if "tests.py" in files:
+ path = os.path.join(dir, "tests.py")
+ if match(rx, path):
+ self.files.append(path)
+ return
return
if not self.is_package(dir):
return
@@ -439,22 +466,32 @@
mod = getattr(mod, part)
return mod
-def get_suite(file):
+class PseudoTestCase:
+ """Minimal test case objects to create error reports.
+
+ If test.py finds something that looks like it should be a test but
+ can't load it or find its test suite, it will report an error
+ using a PseudoTestCase.
+ """
+
+ def __init__(self, name, descr=None):
+ self.name = name
+ self.descr = descr
+
+ def shortDescription(self):
+ return self.descr
+
+ def __str__(self):
+ return "Invalid Test (%s)" % self.name
+
+def get_suite(file, result):
modname = finder.module_from_path(file)
try:
mod = package_import(modname)
- except ImportError, err:
- # print traceback
- print "Error importing %s\n%s" % (modname, err)
- if debug:
- raise
- return None
- try:
- suite_func = mod.test_suite
+ return mod.test_suite()
except AttributeError:
- print "No test_suite() in %s" % file
+ result.addError(PseudoTestCase(modname), sys.exc_info())
return None
- return suite_func()
def filter_testcases(s, rx):
new = unittest.TestSuite()
@@ -534,7 +571,7 @@
progress=progress)
suite = unittest.TestSuite()
for file in files:
- s = get_suite(file)
+ s = get_suite(file, runner.result)
# See if the levels match
dolevel = (level == 0) or level >= getattr(s, "level", 0)
if s is not None and dolevel:
@@ -568,11 +605,8 @@
if not keepStaleBytecode:
os.path.walk(os.curdir, remove_stale_bytecode, None)
-
global pathinit
-
-
-
+
# Get the log.ini file from the current directory instead of possibly
# buried in the build directory. XXX This isn't perfect because if
# log.ini specifies a log file, it'll be relative to the build directory.
@@ -581,7 +615,6 @@
# Initialize the path and cwd
pathinit = PathInit(build, libdir)
-
# Initialize the logging module.
import logging.config
More information about the Zope-Checkins
mailing list