summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_doctest.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_doctest.py')
-rw-r--r--Lib/test/test_doctest.py1004
1 files changed, 1002 insertions, 2 deletions
diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py
index fd3426c..68ac44c 100644
--- a/Lib/test/test_doctest.py
+++ b/Lib/test/test_doctest.py
@@ -1,3 +1,1003 @@
-import doctest
+"""
+Test script for doctest.
+"""
+
from test import test_support
-test_support.run_doctest(doctest)
+import doctest
+
+######################################################################
+## Sample Objects (used by test cases)
+######################################################################
+
+def sample_func(v):
+ """
+ >>> print sample_func(22)
+ 44
+ """
+ return v+v
+
+class SampleClass:
+ """
+ >>> print 1
+ 1
+ """
+ def __init__(self, val):
+ """
+ >>> print SampleClass(12).get()
+ 12
+ """
+ self.val = val
+
+ def double(self):
+ """
+ >>> print SampleClass(12).double().get()
+ 24
+ """
+ return SampleClass(self.val + self.val)
+
+ def get(self):
+ """
+ >>> print SampleClass(-5).get()
+ -5
+ """
+ return self.val
+
+ def a_staticmethod(v):
+ """
+ >>> print SampleClass.a_staticmethod(10)
+ 11
+ """
+ return v+1
+ a_staticmethod = staticmethod(a_staticmethod)
+
+ def a_classmethod(cls, v):
+ """
+ >>> print SampleClass.a_classmethod(10)
+ 12
+ >>> print SampleClass(0).a_classmethod(10)
+ 12
+ """
+ return v+2
+ a_classmethod = classmethod(a_classmethod)
+
+ a_property = property(get, doc="""
+ >>> print SampleClass(22).a_property
+ 22
+ """)
+
+ class NestedClass:
+ """
+ >>> x = SampleClass.NestedClass(5)
+ >>> y = x.square()
+ >>> print y.get()
+ 25
+ """
+ def __init__(self, val=0):
+ """
+ >>> print SampleClass.NestedClass().get()
+ 0
+ """
+ self.val = val
+ def square(self):
+ return SampleClass.NestedClass(self.val*self.val)
+ def get(self):
+ return self.val
+
+class SampleNewStyleClass(object):
+ r"""
+ >>> print '1\n2\n3'
+ 1
+ 2
+ 3
+ """
+ def __init__(self, val):
+ """
+ >>> print SampleNewStyleClass(12).get()
+ 12
+ """
+ self.val = val
+
+ def double(self):
+ """
+ >>> print SampleNewStyleClass(12).double().get()
+ 24
+ """
+ return SampleNewStyleClass(self.val + self.val)
+
+ def get(self):
+ """
+ >>> print SampleNewStyleClass(-5).get()
+ -5
+ """
+ return self.val
+
+######################################################################
+## Test Cases
+######################################################################
+
+def test_Example(): r"""
+Unit tests for the `Example` class.
+
+Example is a simple container class that holds a source code string,
+an expected output string, and a line number (within the docstring):
+
+ >>> example = doctest.Example('print 1', '1\n', 0)
+ >>> (example.source, example.want, example.lineno)
+ ('print 1', '1\n', 0)
+
+The `source` string should end in a newline iff the source spans more
+than one line:
+
+ >>> # Source spans a single line: no terminating newline.
+ >>> e = doctest.Example('print 1', '1\n', 0)
+ >>> e = doctest.Example('print 1\n', '1\n', 0)
+ Traceback (most recent call last):
+ AssertionError
+
+ >>> # Source spans multiple lines: require terminating newline.
+ >>> e = doctest.Example('print 1;\nprint 2\n', '1\n2\n', 0)
+ >>> e = doctest.Example('print 1;\nprint 2', '1\n2\n', 0)
+ Traceback (most recent call last):
+ AssertionError
+
+The `want` string should be terminated by a newline, unless it's the
+empty string:
+
+ >>> e = doctest.Example('print 1', '1\n', 0)
+ >>> e = doctest.Example('print 1', '1', 0)
+ Traceback (most recent call last):
+ AssertionError
+ >>> e = doctest.Example('print', '', 0)
+"""
+
+def test_DocTest(): r"""
+Unit tests for the `DocTest` class.
+
+DocTest is a collection of examples, extracted from a docstring, along
+with information about where the docstring comes from (a name,
+filename, and line number). The docstring is parsed by the `DocTest`
+constructor:
+
+ >>> docstring = '''
+ ... >>> print 12
+ ... 12
+ ...
+ ... Non-example text.
+ ...
+ ... >>> print 'another\example'
+ ... another
+ ... example
+ ... '''
+ >>> globs = {} # globals to run the test in.
+ >>> test = doctest.DocTest(docstring, globs, 'some_test', 'some_file', 20)
+ >>> print test
+ <DocTest some_test from some_file:20 (2 examples)>
+ >>> len(test.examples)
+ 2
+ >>> e1, e2 = test.examples
+ >>> (e1.source, e1.want, e1.lineno)
+ ('print 12', '12\n', 1)
+ >>> (e2.source, e2.want, e2.lineno)
+ ("print 'another\\example'", 'another\nexample\n', 6)
+
+Source information (name, filename, and line number) is available as
+attributes on the doctest object:
+
+ >>> (test.name, test.filename, test.lineno)
+ ('some_test', 'some_file', 20)
+
+The line number of an example within its containing file is found by
+adding the line number of the example and the line number of its
+containing test:
+
+ >>> test.lineno + e1.lineno
+ 21
+ >>> test.lineno + e2.lineno
+ 26
+
+If the docstring contains inconsistant leading whitespace in the
+expected output of an example, then `DocTest` will raise a ValueError:
+
+ >>> docstring = r'''
+ ... >>> print 'bad\nindentation'
+ ... bad
+ ... indentation
+ ... '''
+ >>> doctest.DocTest(docstring, globs, 'some_test', 'filename', 0)
+ Traceback (most recent call last):
+ ValueError: line 3 of the docstring for some_test has inconsistent leading whitespace: ' indentation'
+
+If the docstring contains inconsistent leading whitespace on
+continuation lines, then `DocTest` will raise a ValueError:
+
+ >>> docstring = r'''
+ ... >>> print ('bad indentation',
+ ... ... 2)
+ ... ('bad', 'indentation')
+ ... '''
+ >>> doctest.DocTest(docstring, globs, 'some_test', 'filename', 0)
+ Traceback (most recent call last):
+ ValueError: line 2 of the docstring for some_test has inconsistent leading whitespace: ' ... 2)'
+
+If there's no blank space after a PS1 prompt ('>>>'), then `DocTest`
+will raise a ValueError:
+
+ >>> docstring = '>>>print 1\n1'
+ >>> doctest.DocTest(docstring, globs, 'some_test', 'filename', 0)
+ Traceback (most recent call last):
+ ValueError: line 0 of the docstring for some_test lacks blank after >>>: '>>>print 1'
+"""
+
+# [XX] test that it's getting line numbers right.
+def test_DocTestFinder(): r"""
+Unit tests for the `DocTestFinder` class.
+
+DocTestFinder is used to extract DocTests from an object's docstring
+and the docstrings of its contained objects. It can be used with
+modules, functions, classes, methods, staticmethods, classmethods, and
+properties.
+
+Finding Tests in Functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+For a function whose docstring contains examples, DocTestFinder.find()
+will return a single test (for that function's docstring):
+
+ >>> # Allow ellipsis in the following examples (since the filename
+ >>> # and line number in the traceback can vary):
+ >>> doctest: +ELLIPSIS
+
+ >>> finder = doctest.DocTestFinder()
+ >>> tests = finder.find(sample_func)
+ >>> print tests
+ [<DocTest sample_func from ...:12 (1 example)>]
+ >>> e = tests[0].examples[0]
+ >>> print (e.source, e.want, e.lineno)
+ ('print sample_func(22)', '44\n', 1)
+
+ >>> doctest: -ELLIPSIS # Turn ellipsis back off
+
+If an object has no docstring, then a test is not created for it:
+
+ >>> def no_docstring(v):
+ ... pass
+ >>> finder.find(no_docstring)
+ []
+
+If the function has a docstring with no examples, then a test with no
+examples is returned. (This lets `DocTestRunner` collect statistics
+about which functions have no tests -- but is that useful? And should
+an empty test also be created when there's no docstring?)
+
+ >>> def no_examples(v):
+ ... ''' no doctest examples '''
+ >>> finder.find(no_examples)
+ [<DocTest no_examples from None:1 (no examples)>]
+
+Finding Tests in Classes
+~~~~~~~~~~~~~~~~~~~~~~~~
+For a class, DocTestFinder will create a test for the class's
+docstring, and will recursively explore its contents, including
+methods, classmethods, staticmethods, properties, and nested classes.
+
+ >>> finder = doctest.DocTestFinder()
+ >>> tests = finder.find(SampleClass)
+ >>> tests.sort()
+ >>> for t in tests:
+ ... print '%2s %s' % (len(t.examples), t.name)
+ 1 SampleClass
+ 3 SampleClass.NestedClass
+ 1 SampleClass.NestedClass.__init__
+ 1 SampleClass.__init__
+ 2 SampleClass.a_classmethod
+ 1 SampleClass.a_property
+ 1 SampleClass.a_staticmethod
+ 1 SampleClass.double
+ 1 SampleClass.get
+
+New-style classes are also supported:
+
+ >>> tests = finder.find(SampleNewStyleClass)
+ >>> tests.sort()
+ >>> for t in tests:
+ ... print '%2s %s' % (len(t.examples), t.name)
+ 1 SampleNewStyleClass
+ 1 SampleNewStyleClass.__init__
+ 1 SampleNewStyleClass.double
+ 1 SampleNewStyleClass.get
+
+Finding Tests in Modules
+~~~~~~~~~~~~~~~~~~~~~~~~
+For a module, DocTestFinder will create a test for the class's
+docstring, and will recursively explore its contents, including
+functions, classes, and the `__test__` dictionary, if it exists:
+
+ >>> # A module
+ >>> import new
+ >>> m = new.module('some_module')
+ >>> def triple(val):
+ ... '''
+ ... >>> print tripple(11)
+ ... 33
+ ... '''
+ ... return val*3
+ >>> m.__dict__.update({
+ ... 'sample_func': sample_func,
+ ... 'SampleClass': SampleClass,
+ ... '__doc__': '''
+ ... Module docstring.
+ ... >>> print 'module'
+ ... module
+ ... ''',
+ ... '__test__': {
+ ... 'd': '>>> print 6\n6\n>>> print 7\n7\n',
+ ... 'c': triple}})
+
+ >>> finder = doctest.DocTestFinder()
+ >>> # Use module=test.test_doctest, to prevent doctest from
+ >>> # ignoring the objects since they weren't defined in m.
+ >>> import test.test_doctest
+ >>> tests = finder.find(m, module=test.test_doctest)
+ >>> tests.sort()
+ >>> for t in tests:
+ ... print '%2s %s' % (len(t.examples), t.name)
+ 1 some_module
+ 1 some_module.SampleClass
+ 3 some_module.SampleClass.NestedClass
+ 1 some_module.SampleClass.NestedClass.__init__
+ 1 some_module.SampleClass.__init__
+ 2 some_module.SampleClass.a_classmethod
+ 1 some_module.SampleClass.a_property
+ 1 some_module.SampleClass.a_staticmethod
+ 1 some_module.SampleClass.double
+ 1 some_module.SampleClass.get
+ 1 some_module.c
+ 2 some_module.d
+ 1 some_module.sample_func
+
+Duplicate Removal
+~~~~~~~~~~~~~~~~~
+If a single object is listed twice (under different names), then tests
+will only be generated for it once:
+
+ >>> class TwoNames:
+ ... '''f() and g() are two names for the same method'''
+ ...
+ ... def f(self):
+ ... '''
+ ... >>> print TwoNames().f()
+ ... f
+ ... '''
+ ... return 'f'
+ ...
+ ... g = f # define an alias for f.
+
+ >>> finder = doctest.DocTestFinder()
+ >>> tests = finder.find(TwoNames, ignore_imports=False)
+ >>> tests.sort()
+ >>> print len(tests)
+ 2
+ >>> print tests[0].name
+ TwoNames
+ >>> print tests[1].name in ('TwoNames.f', 'TwoNames.g')
+ True
+
+Filter Functions
+~~~~~~~~~~~~~~~~
+Two filter functions can be used to restrict which objects get
+examined: a name-based filter and an object-based filter.
+
+ >>> def namefilter(prefix, base):
+ ... return base.startswith('a_')
+ >>> tests = doctest.DocTestFinder(namefilter=namefilter).find(SampleClass)
+ >>> tests.sort()
+ >>> for t in tests:
+ ... print '%2s %s' % (len(t.examples), t.name)
+ 1 SampleClass
+ 3 SampleClass.NestedClass
+ 1 SampleClass.NestedClass.__init__
+ 1 SampleClass.__init__
+ 1 SampleClass.double
+ 1 SampleClass.get
+
+ >>> def objfilter(obj):
+ ... return isinstance(obj, (staticmethod, classmethod))
+ >>> tests = doctest.DocTestFinder(objfilter=objfilter).find(SampleClass)
+ >>> tests.sort()
+ >>> for t in tests:
+ ... print '%2s %s' % (len(t.examples), t.name)
+ 1 SampleClass
+ 3 SampleClass.NestedClass
+ 1 SampleClass.NestedClass.__init__
+ 1 SampleClass.__init__
+ 1 SampleClass.a_property
+ 1 SampleClass.double
+ 1 SampleClass.get
+
+If a given object is filtered out, then none of the objects that it
+contains will be added either:
+
+ >>> def namefilter(prefix, base):
+ ... return base == 'NestedClass'
+ >>> tests = doctest.DocTestFinder(namefilter=namefilter).find(SampleClass)
+ >>> tests.sort()
+ >>> for t in tests:
+ ... print '%2s %s' % (len(t.examples), t.name)
+ 1 SampleClass
+ 1 SampleClass.__init__
+ 2 SampleClass.a_classmethod
+ 1 SampleClass.a_property
+ 1 SampleClass.a_staticmethod
+ 1 SampleClass.double
+ 1 SampleClass.get
+
+The filter functions apply to contained objects, and *not* to the
+object explicitly passed to DocTestFinder:
+
+ >>> def namefilter(prefix, base):
+ ... return base == 'SampleClass'
+ >>> tests = doctest.DocTestFinder(namefilter=namefilter).find(SampleClass)
+ >>> len(tests)
+ 9
+
+Turning off Recursion
+~~~~~~~~~~~~~~~~~~~~~
+DocTestFinder can be told not to look for tests in contained objects
+using the `recurse` flag:
+
+ >>> tests = doctest.DocTestFinder(recurse=False).find(SampleClass)
+ >>> tests.sort()
+ >>> for t in tests:
+ ... print '%2s %s' % (len(t.examples), t.name)
+ 1 SampleClass
+"""
+
+class test_DocTestRunner:
+ def basics(): r"""
+Unit tests for the `DocTestRunner` class.
+
+DocTestRunner is used to run DocTest test cases, and to accumulate
+statistics. Here's a simple DocTest case we can use:
+
+ >>> def f(x):
+ ... '''
+ ... >>> x = 12
+ ... >>> print x
+ ... 12
+ ... >>> x/2
+ ... 6
+ ... '''
+ >>> test = doctest.DocTestFinder().find(f)[0]
+
+The main DocTestRunner interface is the `run` method, which runs a
+given DocTest case in a given namespace (globs). It returns a tuple
+`(f,t)`, where `f` is the number of failed tests and `t` is the number
+of tried tests.
+
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ (0, 3)
+
+If any example produces incorrect output, then the test runner reports
+the failure and proceeds to the next example:
+
+ >>> def f(x):
+ ... '''
+ ... >>> x = 12
+ ... >>> print x
+ ... 14
+ ... >>> x/2
+ ... 6
+ ... '''
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=True).run(test)
+ Trying: x = 12
+ Expecting: nothing
+ ok
+ Trying: print x
+ Expecting: 14
+ **********************************************************************
+ Failure in example: print x
+ from line #2 of f
+ Expected: 14
+ Got: 12
+ Trying: x/2
+ Expecting: 6
+ ok
+ (1, 3)
+"""
+ def verbose_flag(): r"""
+The `verbose` flag makes the test runner generate more detailed
+output:
+
+ >>> def f(x):
+ ... '''
+ ... >>> x = 12
+ ... >>> print x
+ ... 12
+ ... >>> x/2
+ ... 6
+ ... '''
+ >>> test = doctest.DocTestFinder().find(f)[0]
+
+ >>> doctest.DocTestRunner(verbose=True).run(test)
+ Trying: x = 12
+ Expecting: nothing
+ ok
+ Trying: print x
+ Expecting: 12
+ ok
+ Trying: x/2
+ Expecting: 6
+ ok
+ (0, 3)
+
+If the `verbose` flag is unspecified, then the output will be verbose
+iff `-v` appears in sys.argv:
+
+ >>> # Save the real sys.argv list.
+ >>> old_argv = sys.argv
+
+ >>> # If -v does not appear in sys.argv, then output isn't verbose.
+ >>> sys.argv = ['test']
+ >>> doctest.DocTestRunner().run(test)
+ (0, 3)
+
+ >>> # If -v does appear in sys.argv, then output is verbose.
+ >>> sys.argv = ['test', '-v']
+ >>> doctest.DocTestRunner().run(test)
+ Trying: x = 12
+ Expecting: nothing
+ ok
+ Trying: print x
+ Expecting: 12
+ ok
+ Trying: x/2
+ Expecting: 6
+ ok
+ (0, 3)
+
+ >>> # Restore sys.argv
+ >>> sys.argv = old_argv
+
+In the remaining examples, the test runner's verbosity will be
+explicitly set, to ensure that the test behavior is consistent.
+ """
+ def exceptions(): r"""
+Tests of `DocTestRunner`'s exception handling.
+
+An expected exception is specified with a traceback message. The
+lines between the first line and the type/value may be omitted or
+replaced with any other string:
+
+ >>> def f(x):
+ ... '''
+ ... >>> x = 12
+ ... >>> print x/0
+ ... Traceback (most recent call last):
+ ... ZeroDivisionError: integer division or modulo by zero
+ ... '''
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ (0, 2)
+
+An example may generate output before it raises an exception; if it
+does, then the output must match the expected output:
+
+ >>> def f(x):
+ ... '''
+ ... >>> x = 12
+ ... >>> print 'pre-exception output', x/0
+ ... pre-exception output
+ ... Traceback (most recent call last):
+ ... ZeroDivisionError: integer division or modulo by zero
+ ... '''
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ (0, 2)
+
+Exception messages may contain newlines:
+
+ >>> def f(x):
+ ... r'''
+ ... >>> raise ValueError, 'multi\nline\nmessage'
+ ... Traceback (most recent call last):
+ ... ValueError: multi
+ ... line
+ ... message
+ ... '''
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ (0, 1)
+
+If an exception is expected, but an exception with the wrong type or
+message is raised, then it is reported as a failure:
+
+ >>> def f(x):
+ ... r'''
+ ... >>> raise ValueError, 'message'
+ ... Traceback (most recent call last):
+ ... ValueError: wrong message
+ ... '''
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ **********************************************************************
+ Failure in example: raise ValueError, 'message'
+ from line #1 of f
+ Expected:
+ Traceback (most recent call last):
+ ValueError: wrong message
+ Got:
+ Traceback (most recent call last):
+ ValueError: message
+ (1, 1)
+
+If an exception is raised but not expected, then it is reported as an
+unexpected exception:
+
+ >>> # Allow ellipsis in the following examples (since the filename
+ >>> # and line number in the traceback can vary):
+ >>> doctest: +ELLIPSIS
+
+ >>> def f(x):
+ ... r'''
+ ... >>> 1/0
+ ... 0
+ ... '''
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ **********************************************************************
+ Failure in example: 1/0
+ from line #1 of f
+ Exception raised:
+ Traceback (most recent call last):
+ ...
+ ZeroDivisionError: integer division or modulo by zero
+ (1, 1)
+
+ >>> doctest: -ELLIPSIS # Turn ellipsis back off:
+"""
+ def optionflags(): r"""
+Tests of `DocTestRunner`'s option flag handling.
+
+Several option flags can be used to customize the behavior of the test
+runner. These are defined as module constants in doctest, and passed
+to the DocTestRunner constructor (multiple constants should be or-ed
+together).
+
+The DONT_ACCEPT_TRUE_FOR_1 flag disables matches between True/False
+and 1/0:
+
+ >>> def f(x):
+ ... '>>> True\n1\n'
+
+ >>> # Without the flag:
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ (0, 1)
+
+ >>> # With the flag:
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> flags = doctest.DONT_ACCEPT_TRUE_FOR_1
+ >>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test)
+ **********************************************************************
+ Failure in example: True
+ from line #0 of f
+ Expected: 1
+ Got: True
+ (1, 1)
+
+The DONT_ACCEPT_BLANKLINE flag disables the match between blank lines
+and the '<BLANKLINE>' marker:
+
+ >>> def f(x):
+ ... '>>> print "a\\n\\nb"\na\n<BLANKLINE>\nb\n'
+
+ >>> # Without the flag:
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ (0, 1)
+
+ >>> # With the flag:
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> flags = doctest.DONT_ACCEPT_BLANKLINE
+ >>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test)
+ **********************************************************************
+ Failure in example: print "a\n\nb"
+ from line #0 of f
+ Expected:
+ a
+ <BLANKLINE>
+ b
+ Got:
+ a
+ <BLANKLINE>
+ b
+ (1, 1)
+
+The NORMALIZE_WHITESPACE flag causes all sequences of whitespace to be
+treated as equal:
+
+ >>> def f(x):
+ ... '>>> print 1, 2, 3\n 1 2\n 3'
+
+ >>> # Without the flag:
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ **********************************************************************
+ Failure in example: print 1, 2, 3
+ from line #0 of f
+ Expected:
+ 1 2
+ 3
+ Got: 1 2 3
+ (1, 1)
+
+ >>> # With the flag:
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> flags = doctest.NORMALIZE_WHITESPACE
+ >>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test)
+ (0, 1)
+
+The ELLIPSIS flag causes ellipsis marker ("...") in the expected
+output to match any substring in the actual output:
+
+ >>> def f(x):
+ ... '>>> print range(15)\n[0, 1, 2, ..., 14]\n'
+
+ >>> # Without the flag:
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ **********************************************************************
+ Failure in example: print range(15)
+ from line #0 of f
+ Expected: [0, 1, 2, ..., 14]
+ Got: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
+ (1, 1)
+
+ >>> # With the flag:
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> flags = doctest.ELLIPSIS
+ >>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test)
+ (0, 1)
+
+The UNIFIED_DIFF flag causes failures that involve multi-line expected
+and actual outputs to be displayed using a unified diff:
+
+ >>> def f(x):
+ ... r'''
+ ... >>> print '\n'.join('abcdefg')
+ ... a
+ ... B
+ ... c
+ ... d
+ ... f
+ ... g
+ ... h
+ ... '''
+
+ >>> # Without the flag:
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ **********************************************************************
+ Failure in example: print '\n'.join('abcdefg')
+ from line #1 of f
+ Expected:
+ a
+ B
+ c
+ d
+ f
+ g
+ h
+ Got:
+ a
+ b
+ c
+ d
+ e
+ f
+ g
+ (1, 1)
+
+ >>> # With the flag:
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> flags = doctest.UNIFIED_DIFF
+ >>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test)
+ **********************************************************************
+ Failure in example: print '\n'.join('abcdefg')
+ from line #1 of f
+ Differences (unified diff):
+ --- Expected
+ +++ Got
+ @@ -1,8 +1,8 @@
+ a
+ -B
+ +b
+ c
+ d
+ +e
+ f
+ g
+ -h
+ <BLANKLINE>
+ (1, 1)
+
+The CONTEXT_DIFF flag causes failures that involve multi-line expected
+and actual outputs to be displayed using a context diff:
+
+ >>> # Reuse f() from the UNIFIED_DIFF example, above.
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> flags = doctest.CONTEXT_DIFF
+ >>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test)
+ **********************************************************************
+ Failure in example: print '\n'.join('abcdefg')
+ from line #1 of f
+ Differences (context diff):
+ *** Expected
+ --- Got
+ ***************
+ *** 1,8 ****
+ a
+ ! B
+ c
+ d
+ f
+ g
+ - h
+ <BLANKLINE>
+ --- 1,8 ----
+ a
+ ! b
+ c
+ d
+ + e
+ f
+ g
+ <BLANKLINE>
+ (1, 1)
+"""
+ def option_directives(): r"""
+Tests of `DocTestRunner`'s option directive mechanism.
+
+Option directives can be used to turn option flags on or off from
+within a DocTest case. The following example shows how a flag can be
+turned on and off. Note that comments on the same line as the option
+directive are ignored.
+
+ >>> def f(x): r'''
+ ... >>> print range(10) # Should fail: no ellipsis
+ ... [0, 1, ..., 9]
+ ...
+ ... >>> doctest: +ELLIPSIS # turn ellipsis on.
+ ... >>> print range(10) # Should succeed
+ ... [0, 1, ..., 9]
+ ...
+ ... >>> doctest: -ELLIPSIS # turn ellipsis back off.
+ ... >>> print range(10) # Should fail: no ellipsis
+ ... [0, 1, ..., 9]
+ ... '''
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ **********************************************************************
+ Failure in example: print range(10) # Should fail: no ellipsis
+ from line #1 of f
+ Expected: [0, 1, ..., 9]
+ Got: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ **********************************************************************
+ Failure in example: print range(10) # Should fail: no ellipsis
+ from line #9 of f
+ Expected: [0, 1, ..., 9]
+ Got: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ (2, 3)
+
+Multiple flags can be toggled by a single option directive:
+
+ >>> def f(x): r'''
+ ... >>> print range(10) # Should fail
+ ... [0, 1, ..., 9]
+ ... >>> doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+ ... >>> print range(10) # Should succeed
+ ... [0, 1, ..., 9]
+ ... '''
+ >>> test = doctest.DocTestFinder().find(f)[0]
+ >>> doctest.DocTestRunner(verbose=False).run(test)
+ **********************************************************************
+ Failure in example: print range(10) # Should fail
+ from line #1 of f
+ Expected: [0, 1, ..., 9]
+ Got: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ (1, 2)
+"""
+
+def test_testsource(): r"""
+Unit tests for `testsource()`.
+
+The testsource() function takes a module and a name, finds the (first)
+test with that name in that module, and converts it to an
+
+ >>> import test.test_doctest
+ >>> name = 'test.test_doctest.sample_func'
+ >>> print doctest.testsource(test.test_doctest, name)
+ print sample_func(22)
+ # Expected:
+ # 44
+
+ >>> name = 'test.test_doctest.SampleNewStyleClass'
+ >>> print doctest.testsource(test.test_doctest, name)
+ print '1\n2\n3'
+ # Expected:
+ # 1
+ # 2
+ # 3
+
+ >>> name = 'test.test_doctest.SampleClass.a_classmethod'
+ >>> print doctest.testsource(test.test_doctest, name)
+ print SampleClass.a_classmethod(10)
+ # Expected:
+ # 12
+ print SampleClass(0).a_classmethod(10)
+ # Expected:
+ # 12
+"""
+
+def test_debug(): r"""
+
+Create a docstring that we want to debug:
+
+ >>> s = '''
+ ... >>> x = 12
+ ... >>> print x
+ ... 12
+ ... '''
+
+Create some fake stdin input, to feed to the debugger:
+
+ >>> import tempfile
+ >>> fake_stdin = tempfile.TemporaryFile(mode='w+')
+ >>> fake_stdin.write('\n'.join(['next', 'print x', 'continue', '']))
+ >>> fake_stdin.seek(0)
+ >>> real_stdin = sys.stdin
+ >>> sys.stdin = fake_stdin
+
+Run the debugger on the docstring, and then restore sys.stdin.
+
+ >>> doctest: +NORMALIZE_WHITESPACE
+ >>> try:
+ ... doctest.debug_src(s)
+ ... finally:
+ ... sys.stdin = real_stdin
+ ... fake_stdin.close()
+ > <string>(1)?()
+ (Pdb) 12
+ --Return--
+ > <string>(1)?()->None
+ (Pdb) 12
+ (Pdb)
+
+"""
+
+######################################################################
+## Main
+######################################################################
+
+def test_main():
+ # Check the doctest cases in doctest itself:
+ test_support.run_doctest(doctest, verbosity=True)
+ # Check the doctest cases defined here:
+ from test import test_doctest
+ test_support.run_doctest(test_doctest, verbosity=True)
+
+import trace, sys, re, StringIO
+def test_coverage(coverdir):
+ tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix,],
+ trace=0, count=1)
+ tracer.run('reload(doctest); test_main()')
+ r = tracer.results()
+ print 'Writing coverage results...'
+ r.write_results(show_missing=True, summary=True,
+ coverdir=coverdir)
+
+if __name__ == '__main__':
+ if '-c' in sys.argv:
+ test_coverage('/tmp/doctest.cover')
+ else:
+ test_main()