[Zope3-checkins] CVS: Zope3 - test.py:1.88
Jeremy Hylton
jeremy at zope.com
Tue Mar 16 00:11:03 EST 2004
Update of /cvs-repository/Zope3
In directory cvs.zope.org:/tmp/cvs-serv26659
Modified Files:
test.py
Log Message:
Report test error when potential test suite module can't be imported.
Add docstring that explains rules for finding tests.
Reflow some paragraphs.
=== Zope3/test.py 1.87 => 1.88 ===
--- Zope3/test.py:1.87 Mon Mar 15 15:41:38 2004
+++ Zope3/test.py Tue Mar 16 00:11:02 2004
@@ -15,20 +15,33 @@
"""
test.py [-aBbcdDfgGhLmPprtTuv] [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.
-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
--build
Run "python setup.py build" before running tests, where "python"
is the version of python used to run test.py. Highly recommended.
- Tests will be run from the build directory. (Note: In Python < 2.3
- the -q flag is added to the setup.py command line.)
+ Tests will be run from the build directory.
-B
Run "python setup.py build_ext -i" before running tests. Tests will be
@@ -62,10 +75,10 @@
Run both unit and functional 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
@@ -100,32 +113,33 @@
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. 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.
-
- When -p is also specified, the meaning of -v is slightly different. With
- -p and no -v only the percent indicator is displayed. With -p and -v
- the test name of the current test is shown to the right of the percent
- indicator. With -p and -vv the test name is not truncated to fit into
- 80 columns and it is not cleared after the test finishes.
+ 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.
+
+ When -p is also specified, the meaning of -v is slightly
+ different. With -p and no -v only the percent indicator is
+ displayed. With -p and -v the test name of the current test is
+ shown to the right of the percent indicator. With -p and -vv the
+ test name is not truncated to fit into 80 columns and it is not
+ cleared after the test finishes.
-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), progress (-p), 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), progress (-p), 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
@@ -199,7 +213,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
@@ -261,9 +275,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:
@@ -341,16 +355,22 @@
self._debug = debug
self._progress = progress
self._profile = profile
+ # 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.result.count = test.countTestCases()
if self._debug:
club_debug(test)
- self._count = test.countTestCases()
if self._profile:
prof = hotshot.Profile("tests_profile.prof")
args = (self, test)
@@ -533,23 +553,41 @@
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)
- traceback.print_exc()
- if debug:
- raise
+ result.addError(PseudoTestCase(modname), sys.exc_info())
return None
try:
suite_func = mod.test_suite
except AttributeError:
- print "No test_suite() in %s" % file
+ result.addError(PseudoTestCase(modname), sys.exc_info())
+ return None
+ try:
+ return suite_func()
+ except:
+ result.addError(PseudoTestCase(modname), sys.exc_info())
return None
- return suite_func()
def filter_testcases(s, rx):
new = unittest.TestSuite()
@@ -632,7 +670,7 @@
descriptions=False)
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:
More information about the Zope3-Checkins
mailing list