to run over the tests in the module. The test for the difflib module
provides a convenient example:
- from test_support import verbose
- import doctest, difflib
- doctest.testmod(difflib, verbose=verbose)
+ import difflib, test_support
+ test_support.run_doctest(difflib)
If the test is successful, nothing is written to stdout (so you should not
create a corresponding output/test_difflib file), but running regrtest
-with -v will give a detailed report, the same as if passing -v to doctest
-(that's what importing verbose from test_support accomplishes).
+with -v will give a detailed report, the same as if passing -v to doctest.
+
+A second argument can be passed to run_doctest to tell doctest to search
+sys.argv for -v instead of using test_support's idea of verbosity. This
+is useful for writing doctest-based tests that aren't simply running a
+doctest'ed Lib module, but contain the doctests themselves. Then at
+times you may want to run such a test directly as a doctest, independent
+of the regrtest framework. The tail end of test_descrtut.py is a good
+example:
+
+ def test_main(verbose=None):
+ import test_support, test.test_descrtut
+ test_support.run_doctest(test.test_descrtut, verbose)
+
+ if __name__ == "__main__":
+ test_main(1)
+
+If run via regrtest, test_main() is called (by regrtest) without specifying
+verbose, and then test_supprot's idea of verbosity is used. But when
+run directly, test_main(1) is called, and then doctest's idea of verbosity
+is used.
See the documentation for the doctest module for information on
writing tests using the doctest framework.
elif verbose:
cfp = sys.stdout
else:
- cfp = Compare(outputfile)
+ cfp = Compare(outputfile, sys.stdout)
except IOError:
cfp = None
print "Warning: can't open", outputfile
print line
class Compare:
- def __init__(self, filename):
+ def __init__(self, filename, origstdout):
+ self.origstdout = origstdout
if os.path.exists(filename):
self.fp = open(filename, 'r')
else:
self.stuffthatmatched = []
def write(self, data):
+ if test_support.suppress_output_comparison():
+ self.origstdout.write(data)
+ return
expected = self.fp.read(len(data))
if data == expected:
self.stuffthatmatched.append(expected)
# Simple test suite for Cookie.py
-from test_support import verify
+from test_support import verify, verbose, run_doctest
import Cookie
-from test_support import verify, verbose
-import doctest
# Currently this only tests SimpleCookie
verify(C['Customer']['path'] == '/acme')
print "If anything blows up after this line, it's from Cookie's doctest."
-doctest.testmod(Cookie)
+run_doctest(Cookie)
# This worms around a bootstrap problem.
# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
# so this works as expected in both ways of running regrtest.
-def test_main():
- import doctest, test.test_descrtut
- doctest.testmod(test.test_descrtut)
+def test_main(verbose=None):
+ # Obscure: import this module as test.test_descrtut instead of as
+ # plain test_descrtut because the name of this module works its way
+ # into the doctest examples, and unless the full test.test_descrtut
+ # business is used the name can change depending on how the test is
+ # invoked.
+ import test_support, test.test_descrtut
+ test_support.run_doctest(test.test_descrtut, verbose)
# This part isn't needed for regrtest, but for running the test directly.
if __name__ == "__main__":
- test_main()
+ test_main(1)
-from test_support import verbose
-import doctest, difflib
-doctest.testmod(difflib, verbose=verbose)
+import difflib, test_support
+test_support.run_doctest(difflib)
-from test_support import verbose
-import doctest
-doctest.testmod(doctest, verbose=verbose)
+import doctest, test_support
+test_support.run_doctest(doctest)
# This worms around a bootstrap problem.
# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
# so this works as expected in both ways of running regrtest.
-def test_main():
- import doctest, test_generators
+def test_main(verbose=None):
+ import doctest, test_support, test_generators
if 0: # change to 1 to run forever (to check for leaks)
while 1:
doctest.master = None
- doctest.testmod(test_generators)
+ test_support.run_doctest(test_generators, verbose)
print ".",
else:
- doctest.testmod(test_generators)
+ test_support.run_doctest(test_generators, verbose)
# This part isn't needed for regrtest, but for running the test directly.
if __name__ == "__main__":
- test_main()
+ test_main(1)
import sys
-
class Error(Exception):
"""Base class for regression test exceptions."""
verbose = 1 # Flag set to 0 by regrtest.py
use_resources = None # Flag set to [] by regrtest.py
+# _output_comparison controls whether regrtest will try to compare stdout
+# with an expected-output file. For straight regrtests, it should.
+# The doctest driver should set_output_comparison(0) for the duration, and
+# restore the old value when it's done.
+# Note that this control is in addition to verbose mode: output will be
+# compared if and only if _output_comparison is true and verbose mode is
+# not in effect.
+_output_comparison = 1
+
+def set_output_comparison(newvalue):
+ global _output_comparison
+ oldvalue = _output_comparison
+ _output_comparison = newvalue
+ return oldvalue
+
+# regrtest's interface to _output_comparison.
+def suppress_output_comparison():
+ return not _output_comparison
+
+
def unload(name):
try:
del sys.modules[name]
raise TestFailed("errors occurred in %s.%s"
% (testclass.__module__, testclass.__name__))
raise TestFailed(err)
+
+#=======================================================================
+# doctest driver.
+
+def run_doctest(module, verbosity=None):
+ """Run doctest on the given module.
+
+ If optional argument verbosity is not specified (or is None), pass
+ test_support's belief about verbosity on to doctest. Else doctest
+ sys.argv for -v.
+ """
+
+ import doctest
+
+ if verbosity is None:
+ verbosity = verbose
+ else:
+ verbosity = None
+
+ oldvalue = set_output_comparison(0)
+ try:
+ f, t = doctest.testmod(module, verbose=verbosity)
+ if f:
+ raise TestFailed("%d of %d doctests failed" % (f, t))
+ finally:
+ set_output_comparison(oldvalue)