|
|
|
@ -4,6 +4,7 @@ Test script for doctest.
|
|
|
|
|
|
|
|
|
|
from test import support
|
|
|
|
|
from test.support import import_helper
|
|
|
|
|
from test.support.pty_helper import FakeInput # used in doctests
|
|
|
|
|
import doctest
|
|
|
|
|
import functools
|
|
|
|
|
import os
|
|
|
|
@ -77,6 +78,15 @@ class SampleClass:
|
|
|
|
|
"""
|
|
|
|
|
return self.val
|
|
|
|
|
|
|
|
|
|
def setter(self, val):
|
|
|
|
|
"""
|
|
|
|
|
>>> s = SampleClass(-5)
|
|
|
|
|
>>> s.setter(1)
|
|
|
|
|
>>> print(s.val)
|
|
|
|
|
1
|
|
|
|
|
"""
|
|
|
|
|
self.val = val
|
|
|
|
|
|
|
|
|
|
def a_staticmethod(v):
|
|
|
|
|
"""
|
|
|
|
|
>>> print(SampleClass.a_staticmethod(10))
|
|
|
|
@ -95,7 +105,7 @@ class SampleClass:
|
|
|
|
|
return v+2
|
|
|
|
|
a_classmethod = classmethod(a_classmethod)
|
|
|
|
|
|
|
|
|
|
a_property = property(get, doc="""
|
|
|
|
|
a_property = property(get, setter, doc="""
|
|
|
|
|
>>> print(SampleClass(22).a_property)
|
|
|
|
|
22
|
|
|
|
|
""")
|
|
|
|
@ -156,25 +166,6 @@ class SampleNewStyleClass(object):
|
|
|
|
|
"""
|
|
|
|
|
return self.val
|
|
|
|
|
|
|
|
|
|
######################################################################
|
|
|
|
|
## Fake stdin (for testing interactive debugging)
|
|
|
|
|
######################################################################
|
|
|
|
|
|
|
|
|
|
class _FakeInput:
|
|
|
|
|
"""
|
|
|
|
|
A fake input stream for pdb's interactive debugger. Whenever a
|
|
|
|
|
line is read, print it (to simulate the user typing it), and then
|
|
|
|
|
return it. The set of lines to return is specified in the
|
|
|
|
|
constructor; they should not have trailing newlines.
|
|
|
|
|
"""
|
|
|
|
|
def __init__(self, lines):
|
|
|
|
|
self.lines = lines
|
|
|
|
|
|
|
|
|
|
def readline(self):
|
|
|
|
|
line = self.lines.pop(0)
|
|
|
|
|
print(line)
|
|
|
|
|
return line+'\n'
|
|
|
|
|
|
|
|
|
|
######################################################################
|
|
|
|
|
## Test Cases
|
|
|
|
|
######################################################################
|
|
|
|
@ -468,14 +459,14 @@ will return a single test (for that function's docstring):
|
|
|
|
|
|
|
|
|
|
We'll simulate a __file__ attr that ends in pyc:
|
|
|
|
|
|
|
|
|
|
>>> import test.test_doctest
|
|
|
|
|
>>> old = test.test_doctest.__file__
|
|
|
|
|
>>> test.test_doctest.__file__ = 'test_doctest.pyc'
|
|
|
|
|
>>> from test.test_doctest import test_doctest
|
|
|
|
|
>>> old = test_doctest.__file__
|
|
|
|
|
>>> test_doctest.__file__ = 'test_doctest.pyc'
|
|
|
|
|
|
|
|
|
|
>>> tests = finder.find(sample_func)
|
|
|
|
|
|
|
|
|
|
>>> print(tests) # doctest: +ELLIPSIS
|
|
|
|
|
[<DocTest sample_func from test_doctest.py:32 (1 example)>]
|
|
|
|
|
[<DocTest sample_func from test_doctest.py:33 (1 example)>]
|
|
|
|
|
|
|
|
|
|
The exact name depends on how test_doctest was invoked, so allow for
|
|
|
|
|
leading path components.
|
|
|
|
@ -483,7 +474,7 @@ leading path components.
|
|
|
|
|
>>> tests[0].filename # doctest: +ELLIPSIS
|
|
|
|
|
'...test_doctest.py'
|
|
|
|
|
|
|
|
|
|
>>> test.test_doctest.__file__ = old
|
|
|
|
|
>>> test_doctest.__file__ = old
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>>> e = tests[0].examples[0]
|
|
|
|
@ -537,6 +528,7 @@ methods, classmethods, staticmethods, properties, and nested classes.
|
|
|
|
|
1 SampleClass.a_staticmethod
|
|
|
|
|
1 SampleClass.double
|
|
|
|
|
1 SampleClass.get
|
|
|
|
|
3 SampleClass.setter
|
|
|
|
|
|
|
|
|
|
New-style classes are also supported:
|
|
|
|
|
|
|
|
|
@ -576,10 +568,10 @@ functions, classes, and the `__test__` dictionary, if it exists:
|
|
|
|
|
... 'c': triple}})
|
|
|
|
|
|
|
|
|
|
>>> finder = doctest.DocTestFinder()
|
|
|
|
|
>>> # Use module=test.test_doctest, to prevent doctest from
|
|
|
|
|
>>> # Use module=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)
|
|
|
|
|
>>> from test.test_doctest import test_doctest
|
|
|
|
|
>>> tests = finder.find(m, module=test_doctest)
|
|
|
|
|
>>> for t in tests:
|
|
|
|
|
... print('%2s %s' % (len(t.examples), t.name))
|
|
|
|
|
1 some_module
|
|
|
|
@ -593,23 +585,38 @@ functions, classes, and the `__test__` dictionary, if it exists:
|
|
|
|
|
1 some_module.SampleClass.a_staticmethod
|
|
|
|
|
1 some_module.SampleClass.double
|
|
|
|
|
1 some_module.SampleClass.get
|
|
|
|
|
3 some_module.SampleClass.setter
|
|
|
|
|
1 some_module.__test__.c
|
|
|
|
|
2 some_module.__test__.d
|
|
|
|
|
1 some_module.sample_func
|
|
|
|
|
|
|
|
|
|
However, doctest will ignore imported objects from other modules
|
|
|
|
|
(without proper `module=`):
|
|
|
|
|
|
|
|
|
|
>>> import types
|
|
|
|
|
>>> m = types.ModuleType('poluted_namespace')
|
|
|
|
|
>>> m.__dict__.update({
|
|
|
|
|
... 'sample_func': sample_func,
|
|
|
|
|
... 'SampleClass': SampleClass,
|
|
|
|
|
... })
|
|
|
|
|
|
|
|
|
|
>>> finder = doctest.DocTestFinder()
|
|
|
|
|
>>> finder.find(m)
|
|
|
|
|
[]
|
|
|
|
|
|
|
|
|
|
Duplicate Removal
|
|
|
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
|
If a single object is listed twice (under different names), then tests
|
|
|
|
|
will only be generated for it once:
|
|
|
|
|
|
|
|
|
|
>>> from test import doctest_aliases
|
|
|
|
|
>>> from test.test_doctest import doctest_aliases
|
|
|
|
|
>>> assert doctest_aliases.TwoNames.f
|
|
|
|
|
>>> assert doctest_aliases.TwoNames.g
|
|
|
|
|
>>> tests = excl_empty_finder.find(doctest_aliases)
|
|
|
|
|
>>> print(len(tests))
|
|
|
|
|
2
|
|
|
|
|
>>> print(tests[0].name)
|
|
|
|
|
test.doctest_aliases.TwoNames
|
|
|
|
|
test.test_doctest.doctest_aliases.TwoNames
|
|
|
|
|
|
|
|
|
|
TwoNames.f and TwoNames.g are bound to the same object.
|
|
|
|
|
We can't guess which will be found in doctest's traversal of
|
|
|
|
@ -635,6 +642,7 @@ By default, an object with no doctests doesn't create any tests:
|
|
|
|
|
1 SampleClass.a_staticmethod
|
|
|
|
|
1 SampleClass.double
|
|
|
|
|
1 SampleClass.get
|
|
|
|
|
3 SampleClass.setter
|
|
|
|
|
|
|
|
|
|
By default, that excluded objects with no doctests. exclude_empty=False
|
|
|
|
|
tells it to include (empty) tests for objects with no doctests. This feature
|
|
|
|
@ -656,28 +664,29 @@ displays.
|
|
|
|
|
1 SampleClass.a_staticmethod
|
|
|
|
|
1 SampleClass.double
|
|
|
|
|
1 SampleClass.get
|
|
|
|
|
3 SampleClass.setter
|
|
|
|
|
|
|
|
|
|
When used with `exclude_empty=False` we are also interested in line numbers
|
|
|
|
|
of doctests that are empty.
|
|
|
|
|
It used to be broken for quite some time until `bpo-28249`.
|
|
|
|
|
|
|
|
|
|
>>> from test import doctest_lineno
|
|
|
|
|
>>> from test.test_doctest import doctest_lineno
|
|
|
|
|
>>> tests = doctest.DocTestFinder(exclude_empty=False).find(doctest_lineno)
|
|
|
|
|
>>> for t in tests:
|
|
|
|
|
... print('%5s %s' % (t.lineno, t.name))
|
|
|
|
|
None test.doctest_lineno
|
|
|
|
|
22 test.doctest_lineno.ClassWithDocstring
|
|
|
|
|
30 test.doctest_lineno.ClassWithDoctest
|
|
|
|
|
None test.doctest_lineno.ClassWithoutDocstring
|
|
|
|
|
None test.doctest_lineno.MethodWrapper
|
|
|
|
|
53 test.doctest_lineno.MethodWrapper.classmethod_with_doctest
|
|
|
|
|
39 test.doctest_lineno.MethodWrapper.method_with_docstring
|
|
|
|
|
45 test.doctest_lineno.MethodWrapper.method_with_doctest
|
|
|
|
|
None test.doctest_lineno.MethodWrapper.method_without_docstring
|
|
|
|
|
61 test.doctest_lineno.MethodWrapper.property_with_doctest
|
|
|
|
|
4 test.doctest_lineno.func_with_docstring
|
|
|
|
|
12 test.doctest_lineno.func_with_doctest
|
|
|
|
|
None test.doctest_lineno.func_without_docstring
|
|
|
|
|
None test.test_doctest.doctest_lineno
|
|
|
|
|
22 test.test_doctest.doctest_lineno.ClassWithDocstring
|
|
|
|
|
30 test.test_doctest.doctest_lineno.ClassWithDoctest
|
|
|
|
|
None test.test_doctest.doctest_lineno.ClassWithoutDocstring
|
|
|
|
|
None test.test_doctest.doctest_lineno.MethodWrapper
|
|
|
|
|
53 test.test_doctest.doctest_lineno.MethodWrapper.classmethod_with_doctest
|
|
|
|
|
39 test.test_doctest.doctest_lineno.MethodWrapper.method_with_docstring
|
|
|
|
|
45 test.test_doctest.doctest_lineno.MethodWrapper.method_with_doctest
|
|
|
|
|
None test.test_doctest.doctest_lineno.MethodWrapper.method_without_docstring
|
|
|
|
|
61 test.test_doctest.doctest_lineno.MethodWrapper.property_with_doctest
|
|
|
|
|
4 test.test_doctest.doctest_lineno.func_with_docstring
|
|
|
|
|
12 test.test_doctest.doctest_lineno.func_with_doctest
|
|
|
|
|
None test.test_doctest.doctest_lineno.func_without_docstring
|
|
|
|
|
|
|
|
|
|
Turning off Recursion
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
@ -1924,9 +1933,9 @@ test with that name in that module, and converts it to a script. The
|
|
|
|
|
example code is converted to regular Python code. The surrounding
|
|
|
|
|
words and expected output are converted to comments:
|
|
|
|
|
|
|
|
|
|
>>> import test.test_doctest
|
|
|
|
|
>>> name = 'test.test_doctest.sample_func'
|
|
|
|
|
>>> print(doctest.testsource(test.test_doctest, name))
|
|
|
|
|
>>> from test.test_doctest import test_doctest
|
|
|
|
|
>>> name = 'test.test_doctest.test_doctest.sample_func'
|
|
|
|
|
>>> print(doctest.testsource(test_doctest, name))
|
|
|
|
|
# Blah blah
|
|
|
|
|
#
|
|
|
|
|
print(sample_func(22))
|
|
|
|
@ -1936,8 +1945,8 @@ words and expected output are converted to comments:
|
|
|
|
|
# Yee ha!
|
|
|
|
|
<BLANKLINE>
|
|
|
|
|
|
|
|
|
|
>>> name = 'test.test_doctest.SampleNewStyleClass'
|
|
|
|
|
>>> print(doctest.testsource(test.test_doctest, name))
|
|
|
|
|
>>> name = 'test.test_doctest.test_doctest.SampleNewStyleClass'
|
|
|
|
|
>>> print(doctest.testsource(test_doctest, name))
|
|
|
|
|
print('1\n2\n3')
|
|
|
|
|
# Expected:
|
|
|
|
|
## 1
|
|
|
|
@ -1945,8 +1954,8 @@ words and expected output are converted to comments:
|
|
|
|
|
## 3
|
|
|
|
|
<BLANKLINE>
|
|
|
|
|
|
|
|
|
|
>>> name = 'test.test_doctest.SampleClass.a_classmethod'
|
|
|
|
|
>>> print(doctest.testsource(test.test_doctest, name))
|
|
|
|
|
>>> name = 'test.test_doctest.test_doctest.SampleClass.a_classmethod'
|
|
|
|
|
>>> print(doctest.testsource(test_doctest, name))
|
|
|
|
|
print(SampleClass.a_classmethod(10))
|
|
|
|
|
# Expected:
|
|
|
|
|
## 12
|
|
|
|
@ -1969,7 +1978,7 @@ Create a docstring that we want to debug:
|
|
|
|
|
Create some fake stdin input, to feed to the debugger:
|
|
|
|
|
|
|
|
|
|
>>> real_stdin = sys.stdin
|
|
|
|
|
>>> sys.stdin = _FakeInput(['next', 'print(x)', 'continue'])
|
|
|
|
|
>>> sys.stdin = FakeInput(['next', 'print(x)', 'continue'])
|
|
|
|
|
|
|
|
|
|
Run the debugger on the docstring, and then restore sys.stdin.
|
|
|
|
|
|
|
|
|
@ -2012,7 +2021,7 @@ if not hasattr(sys, 'gettrace') or not sys.gettrace():
|
|
|
|
|
captures our debugger input:
|
|
|
|
|
|
|
|
|
|
>>> real_stdin = sys.stdin
|
|
|
|
|
>>> sys.stdin = _FakeInput([
|
|
|
|
|
>>> sys.stdin = FakeInput([
|
|
|
|
|
... 'print(x)', # print data defined by the example
|
|
|
|
|
... 'continue', # stop debugging
|
|
|
|
|
... ''])
|
|
|
|
@ -2039,7 +2048,7 @@ if not hasattr(sys, 'gettrace') or not sys.gettrace():
|
|
|
|
|
... '''
|
|
|
|
|
>>> test = parser.get_doctest(doc, globals(), "foo-bar@baz", "foo-bar@baz.py", 0)
|
|
|
|
|
>>> real_stdin = sys.stdin
|
|
|
|
|
>>> sys.stdin = _FakeInput([
|
|
|
|
|
>>> sys.stdin = FakeInput([
|
|
|
|
|
... 'print(y)', # print data defined in the function
|
|
|
|
|
... 'up', # out of function
|
|
|
|
|
... 'print(x)', # print data defined by the example
|
|
|
|
@ -2051,7 +2060,7 @@ if not hasattr(sys, 'gettrace') or not sys.gettrace():
|
|
|
|
|
... finally:
|
|
|
|
|
... sys.stdin = real_stdin
|
|
|
|
|
--Return--
|
|
|
|
|
> <doctest test.test_doctest.test_pdb_set_trace[7]>(3)calls_set_trace()->None
|
|
|
|
|
> <doctest test.test_doctest.test_doctest.test_pdb_set_trace[7]>(3)calls_set_trace()->None
|
|
|
|
|
-> import pdb; pdb.set_trace()
|
|
|
|
|
(Pdb) print(y)
|
|
|
|
|
2
|
|
|
|
@ -2076,7 +2085,7 @@ if not hasattr(sys, 'gettrace') or not sys.gettrace():
|
|
|
|
|
... '''
|
|
|
|
|
>>> test = parser.get_doctest(doc, globals(), "foo-bar@baz", "foo-bar@baz.py", 0)
|
|
|
|
|
>>> real_stdin = sys.stdin
|
|
|
|
|
>>> sys.stdin = _FakeInput([
|
|
|
|
|
>>> sys.stdin = FakeInput([
|
|
|
|
|
... 'list', # list source from example 2
|
|
|
|
|
... 'next', # return from g()
|
|
|
|
|
... 'list', # list source from example 1
|
|
|
|
@ -2148,7 +2157,7 @@ if not hasattr(sys, 'gettrace') or not sys.gettrace():
|
|
|
|
|
>>> runner = doctest.DocTestRunner(verbose=False)
|
|
|
|
|
>>> test = parser.get_doctest(doc, globals(), "foo-bar@baz", "foo-bar@baz.py", 0)
|
|
|
|
|
>>> real_stdin = sys.stdin
|
|
|
|
|
>>> sys.stdin = _FakeInput([
|
|
|
|
|
>>> sys.stdin = FakeInput([
|
|
|
|
|
... 'print(y)', # print data defined in the function
|
|
|
|
|
... 'step', 'step', 'step', 'step', 'step', 'step', 'print(z)',
|
|
|
|
|
... 'up', 'print(x)',
|
|
|
|
@ -2162,39 +2171,39 @@ if not hasattr(sys, 'gettrace') or not sys.gettrace():
|
|
|
|
|
... finally:
|
|
|
|
|
... sys.stdin = real_stdin
|
|
|
|
|
... # doctest: +REPORT_NDIFF
|
|
|
|
|
> <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(5)calls_set_trace()
|
|
|
|
|
> <doctest test.test_doctest.test_doctest.test_pdb_set_trace_nested[0]>(5)calls_set_trace()
|
|
|
|
|
-> self.f1()
|
|
|
|
|
(Pdb) print(y)
|
|
|
|
|
1
|
|
|
|
|
(Pdb) step
|
|
|
|
|
--Call--
|
|
|
|
|
> <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(7)f1()
|
|
|
|
|
> <doctest test.test_doctest.test_doctest.test_pdb_set_trace_nested[0]>(7)f1()
|
|
|
|
|
-> def f1(self):
|
|
|
|
|
(Pdb) step
|
|
|
|
|
> <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(8)f1()
|
|
|
|
|
> <doctest test.test_doctest.test_doctest.test_pdb_set_trace_nested[0]>(8)f1()
|
|
|
|
|
-> x = 1
|
|
|
|
|
(Pdb) step
|
|
|
|
|
> <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(9)f1()
|
|
|
|
|
> <doctest test.test_doctest.test_doctest.test_pdb_set_trace_nested[0]>(9)f1()
|
|
|
|
|
-> self.f2()
|
|
|
|
|
(Pdb) step
|
|
|
|
|
--Call--
|
|
|
|
|
> <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(11)f2()
|
|
|
|
|
> <doctest test.test_doctest.test_doctest.test_pdb_set_trace_nested[0]>(11)f2()
|
|
|
|
|
-> def f2(self):
|
|
|
|
|
(Pdb) step
|
|
|
|
|
> <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(12)f2()
|
|
|
|
|
> <doctest test.test_doctest.test_doctest.test_pdb_set_trace_nested[0]>(12)f2()
|
|
|
|
|
-> z = 1
|
|
|
|
|
(Pdb) step
|
|
|
|
|
> <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(13)f2()
|
|
|
|
|
> <doctest test.test_doctest.test_doctest.test_pdb_set_trace_nested[0]>(13)f2()
|
|
|
|
|
-> z = 2
|
|
|
|
|
(Pdb) print(z)
|
|
|
|
|
1
|
|
|
|
|
(Pdb) up
|
|
|
|
|
> <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(9)f1()
|
|
|
|
|
> <doctest test.test_doctest.test_doctest.test_pdb_set_trace_nested[0]>(9)f1()
|
|
|
|
|
-> self.f2()
|
|
|
|
|
(Pdb) print(x)
|
|
|
|
|
1
|
|
|
|
|
(Pdb) up
|
|
|
|
|
> <doctest test.test_doctest.test_pdb_set_trace_nested[0]>(5)calls_set_trace()
|
|
|
|
|
> <doctest test.test_doctest.test_doctest.test_pdb_set_trace_nested[0]>(5)calls_set_trace()
|
|
|
|
|
-> self.f1()
|
|
|
|
|
(Pdb) print(y)
|
|
|
|
|
1
|
|
|
|
@ -2214,39 +2223,39 @@ def test_DocTestSuite():
|
|
|
|
|
by passing a module object:
|
|
|
|
|
|
|
|
|
|
>>> import unittest
|
|
|
|
|
>>> import test.sample_doctest
|
|
|
|
|
>>> suite = doctest.DocTestSuite(test.sample_doctest)
|
|
|
|
|
>>> import test.test_doctest.sample_doctest
|
|
|
|
|
>>> suite = doctest.DocTestSuite(test.test_doctest.sample_doctest)
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=9 errors=0 failures=4>
|
|
|
|
|
|
|
|
|
|
We can also supply the module by name:
|
|
|
|
|
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.sample_doctest')
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.test_doctest.sample_doctest')
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=9 errors=0 failures=4>
|
|
|
|
|
|
|
|
|
|
The module need not contain any doctest examples:
|
|
|
|
|
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.sample_doctest_no_doctests')
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.test_doctest.sample_doctest_no_doctests')
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=0 errors=0 failures=0>
|
|
|
|
|
|
|
|
|
|
The module need not contain any docstrings either:
|
|
|
|
|
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.sample_doctest_no_docstrings')
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.test_doctest.sample_doctest_no_docstrings')
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=0 errors=0 failures=0>
|
|
|
|
|
|
|
|
|
|
We can use the current module:
|
|
|
|
|
|
|
|
|
|
>>> suite = test.sample_doctest.test_suite()
|
|
|
|
|
>>> suite = test.test_doctest.sample_doctest.test_suite()
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=9 errors=0 failures=4>
|
|
|
|
|
|
|
|
|
|
We can also provide a DocTestFinder:
|
|
|
|
|
|
|
|
|
|
>>> finder = doctest.DocTestFinder()
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.sample_doctest',
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.test_doctest.sample_doctest',
|
|
|
|
|
... test_finder=finder)
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=9 errors=0 failures=4>
|
|
|
|
@ -2254,7 +2263,7 @@ def test_DocTestSuite():
|
|
|
|
|
The DocTestFinder need not return any tests:
|
|
|
|
|
|
|
|
|
|
>>> finder = doctest.DocTestFinder()
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.sample_doctest_no_docstrings',
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.test_doctest.sample_doctest_no_docstrings',
|
|
|
|
|
... test_finder=finder)
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=0 errors=0 failures=0>
|
|
|
|
@ -2263,14 +2272,14 @@ def test_DocTestSuite():
|
|
|
|
|
used instead of the module globals. Here we'll pass an empty
|
|
|
|
|
globals, triggering an extra error:
|
|
|
|
|
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.sample_doctest', globs={})
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.test_doctest.sample_doctest', globs={})
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=9 errors=0 failures=5>
|
|
|
|
|
|
|
|
|
|
Alternatively, we can provide extra globals. Here we'll make an
|
|
|
|
|
error go away by providing an extra global variable:
|
|
|
|
|
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.sample_doctest',
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.test_doctest.sample_doctest',
|
|
|
|
|
... extraglobs={'y': 1})
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=9 errors=0 failures=3>
|
|
|
|
@ -2278,7 +2287,7 @@ def test_DocTestSuite():
|
|
|
|
|
You can pass option flags. Here we'll cause an extra error
|
|
|
|
|
by disabling the blank-line feature:
|
|
|
|
|
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.sample_doctest',
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.test_doctest.sample_doctest',
|
|
|
|
|
... optionflags=doctest.DONT_ACCEPT_BLANKLINE)
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=9 errors=0 failures=5>
|
|
|
|
@ -2286,27 +2295,27 @@ def test_DocTestSuite():
|
|
|
|
|
You can supply setUp and tearDown functions:
|
|
|
|
|
|
|
|
|
|
>>> def setUp(t):
|
|
|
|
|
... import test.test_doctest
|
|
|
|
|
... test.test_doctest.sillySetup = True
|
|
|
|
|
... from test.test_doctest import test_doctest
|
|
|
|
|
... test_doctest.sillySetup = True
|
|
|
|
|
|
|
|
|
|
>>> def tearDown(t):
|
|
|
|
|
... import test.test_doctest
|
|
|
|
|
... del test.test_doctest.sillySetup
|
|
|
|
|
... from test.test_doctest import test_doctest
|
|
|
|
|
... del test_doctest.sillySetup
|
|
|
|
|
|
|
|
|
|
Here, we installed a silly variable that the test expects:
|
|
|
|
|
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.sample_doctest',
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.test_doctest.sample_doctest',
|
|
|
|
|
... setUp=setUp, tearDown=tearDown)
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=9 errors=0 failures=3>
|
|
|
|
|
|
|
|
|
|
But the tearDown restores sanity:
|
|
|
|
|
|
|
|
|
|
>>> import test.test_doctest
|
|
|
|
|
>>> test.test_doctest.sillySetup
|
|
|
|
|
>>> from test.test_doctest import test_doctest
|
|
|
|
|
>>> test_doctest.sillySetup
|
|
|
|
|
Traceback (most recent call last):
|
|
|
|
|
...
|
|
|
|
|
AttributeError: module 'test.test_doctest' has no attribute 'sillySetup'
|
|
|
|
|
AttributeError: module 'test.test_doctest.test_doctest' has no attribute 'sillySetup'
|
|
|
|
|
|
|
|
|
|
The setUp and tearDown functions are passed test objects. Here
|
|
|
|
|
we'll use the setUp function to supply the missing variable y:
|
|
|
|
@ -2314,7 +2323,7 @@ def test_DocTestSuite():
|
|
|
|
|
>>> def setUp(test):
|
|
|
|
|
... test.globs['y'] = 1
|
|
|
|
|
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.sample_doctest', setUp=setUp)
|
|
|
|
|
>>> suite = doctest.DocTestSuite('test.test_doctest.sample_doctest', setUp=setUp)
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=9 errors=0 failures=3>
|
|
|
|
|
|
|
|
|
@ -2345,7 +2354,7 @@ def test_DocFileSuite():
|
|
|
|
|
>>> suite = doctest.DocFileSuite('test_doctest.txt',
|
|
|
|
|
... 'test_doctest2.txt',
|
|
|
|
|
... 'test_doctest4.txt',
|
|
|
|
|
... package='test')
|
|
|
|
|
... package='test.test_doctest')
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=3 errors=0 failures=2>
|
|
|
|
|
|
|
|
|
@ -2361,7 +2370,7 @@ def test_DocFileSuite():
|
|
|
|
|
... suite = doctest.DocFileSuite('test_doctest.txt',
|
|
|
|
|
... 'test_doctest2.txt',
|
|
|
|
|
... 'test_doctest4.txt',
|
|
|
|
|
... package='test')
|
|
|
|
|
... package='test.test_doctest')
|
|
|
|
|
... suite.run(unittest.TestResult())
|
|
|
|
|
... finally:
|
|
|
|
|
... if added_loader:
|
|
|
|
@ -2371,16 +2380,17 @@ def test_DocFileSuite():
|
|
|
|
|
'/' should be used as a path separator. It will be converted
|
|
|
|
|
to a native separator at run time:
|
|
|
|
|
|
|
|
|
|
>>> suite = doctest.DocFileSuite('../test/test_doctest.txt')
|
|
|
|
|
>>> suite = doctest.DocFileSuite('../test_doctest/test_doctest.txt')
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=1 errors=0 failures=1>
|
|
|
|
|
|
|
|
|
|
If DocFileSuite is used from an interactive session, then files
|
|
|
|
|
are resolved relative to the directory of sys.argv[0]:
|
|
|
|
|
|
|
|
|
|
>>> import types, os.path, test.test_doctest
|
|
|
|
|
>>> import types, os.path
|
|
|
|
|
>>> from test.test_doctest import test_doctest
|
|
|
|
|
>>> save_argv = sys.argv
|
|
|
|
|
>>> sys.argv = [test.test_doctest.__file__]
|
|
|
|
|
>>> sys.argv = [test_doctest.__file__]
|
|
|
|
|
>>> suite = doctest.DocFileSuite('test_doctest.txt',
|
|
|
|
|
... package=types.ModuleType('__main__'))
|
|
|
|
|
>>> sys.argv = save_argv
|
|
|
|
@ -2390,7 +2400,7 @@ def test_DocFileSuite():
|
|
|
|
|
working directory):
|
|
|
|
|
|
|
|
|
|
>>> # Get the absolute path of the test package.
|
|
|
|
|
>>> test_doctest_path = os.path.abspath(test.test_doctest.__file__)
|
|
|
|
|
>>> test_doctest_path = os.path.abspath(test_doctest.__file__)
|
|
|
|
|
>>> test_pkg_path = os.path.split(test_doctest_path)[0]
|
|
|
|
|
|
|
|
|
|
>>> # Use it to find the absolute path of test_doctest.txt.
|
|
|
|
@ -2430,12 +2440,12 @@ def test_DocFileSuite():
|
|
|
|
|
And, you can provide setUp and tearDown functions:
|
|
|
|
|
|
|
|
|
|
>>> def setUp(t):
|
|
|
|
|
... import test.test_doctest
|
|
|
|
|
... test.test_doctest.sillySetup = True
|
|
|
|
|
... from test.test_doctest import test_doctest
|
|
|
|
|
... test_doctest.sillySetup = True
|
|
|
|
|
|
|
|
|
|
>>> def tearDown(t):
|
|
|
|
|
... import test.test_doctest
|
|
|
|
|
... del test.test_doctest.sillySetup
|
|
|
|
|
... from test.test_doctest import test_doctest
|
|
|
|
|
... del test_doctest.sillySetup
|
|
|
|
|
|
|
|
|
|
Here, we installed a silly variable that the test expects:
|
|
|
|
|
|
|
|
|
@ -2448,11 +2458,11 @@ def test_DocFileSuite():
|
|
|
|
|
|
|
|
|
|
But the tearDown restores sanity:
|
|
|
|
|
|
|
|
|
|
>>> import test.test_doctest
|
|
|
|
|
>>> test.test_doctest.sillySetup
|
|
|
|
|
>>> from test.test_doctest import test_doctest
|
|
|
|
|
>>> test_doctest.sillySetup
|
|
|
|
|
Traceback (most recent call last):
|
|
|
|
|
...
|
|
|
|
|
AttributeError: module 'test.test_doctest' has no attribute 'sillySetup'
|
|
|
|
|
AttributeError: module 'test.test_doctest.test_doctest' has no attribute 'sillySetup'
|
|
|
|
|
|
|
|
|
|
The setUp and tearDown functions are passed test objects.
|
|
|
|
|
Here, we'll use a setUp function to set the favorite color in
|
|
|
|
@ -3212,8 +3222,8 @@ def test_run_doctestsuite_multiple_times():
|
|
|
|
|
http://bugs.python.org/issue9736
|
|
|
|
|
|
|
|
|
|
>>> import unittest
|
|
|
|
|
>>> import test.sample_doctest
|
|
|
|
|
>>> suite = doctest.DocTestSuite(test.sample_doctest)
|
|
|
|
|
>>> import test.test_doctest.sample_doctest
|
|
|
|
|
>>> suite = doctest.DocTestSuite(test.test_doctest.sample_doctest)
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
|
<unittest.result.TestResult run=9 errors=0 failures=4>
|
|
|
|
|
>>> suite.run(unittest.TestResult())
|
|
|
|
@ -3390,4 +3400,4 @@ def load_tests(loader, tests, pattern):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
unittest.main(module='test.test_doctest')
|
|
|
|
|
unittest.main(module='test.test_doctest.test_doctest')
|