8 tests in doctest
6 tests in doctest.Tester
10 tests in doctest.Tester.merge
- 7 tests in doctest.Tester.rundict
+ 14 tests in doctest.Tester.rundict
3 tests in doctest.Tester.rundoc
3 tests in doctest.Tester.runstring
2 tests in doctest.__test__._TestClass
1 tests in doctest.__test__._TestClass.square
2 tests in doctest.__test__.string
7 tests in doctest.is_private
-53 tests in 17 items.
-53 passed and 0 failed.
+60 tests in 17 items.
+60 passed and 0 failed.
Test passed.
"""
from inspect import isclass as _isclass
from inspect import isfunction as _isfunction
from inspect import ismodule as _ismodule
+from inspect import classify_class_attrs as _classify_class_attrs
# Extract interactive examples from a string. Return a list of triples,
# (source, outcome, lineno). "source" is the source code, and ends
print f, "of", t, "examples failed in", name + ".__doc__"
self.__record_outcome(name, f, t)
if _isclass(object):
- f2, t2 = self.rundict(object.__dict__, name)
- f = f + f2
- t = t + t2
+ # In 2.2, class and static methods complicate life. Build
+ # a dict "that works", by hook or by crook.
+ d = {}
+ for tag, kind, homecls, value in _classify_class_attrs(object):
+
+ if homecls is not object:
+ # Only look at names defined immediately by the class.
+ continue
+
+ elif self.isprivate(name, tag):
+ continue
+
+ elif kind == "method":
+ # value is already a function
+ d[tag] = value
+
+ elif kind == "static method":
+ # value isn't a function, but getattr reveals one
+ d[tag] = getattr(object, tag)
+
+ elif kind == "class method":
+ # Hmm. A classmethod object doesn't seem to reveal
+ # enough. But getattr turns it into a bound method,
+ # and from there .im_func retrieves the underlying
+ # function.
+ d[tag] = getattr(object, tag).im_func
+
+ elif kind == "property":
+ # The methods implementing the property have their
+ # own docstrings -- but the property may have one too.
+ if value.__doc__ is not None:
+ d[tag] = str(value.__doc__)
+
+ elif kind == "data":
+ # Grab nested classes.
+ if _isclass(value):
+ d[tag] = value
+
+ else:
+ raise ValueError("teach doctest about %r" % kind)
+
+ f2, t2 = self.run__test__(d, name)
+ f += f2
+ t += t2
+
return f, t
def rundict(self, d, name, module=None):
--- /dev/null
+"""A module to test whether doctest recognizes some 2.2 features,
+like static and class methods.
+
+>>> print 'yup' # 1
+yup
+"""
+
+import test_support
+
+# XXX The class docstring is skipped.
+class C(object):
+ """Class C.
+
+ >>> print C() # 2
+ 42
+ """
+
+ def __init__(self):
+ """C.__init__.
+
+ >>> print C() # 3
+ 42
+ """
+
+ def __str__(self):
+ """
+ >>> print C() # 4
+ 42
+ """
+ return "42"
+
+ # XXX The class docstring is skipped.
+ class D(object):
+ """A nested D class.
+
+ >>> print "In D!" # 5
+ In D!
+ """
+
+ def nested(self):
+ """
+ >>> print 3 # 6
+ 3
+ """
+
+ def getx(self):
+ """
+ >>> c = C() # 7
+ >>> c.x = 12 # 8
+ >>> print c.x # 9
+ -12
+ """
+ return -self._x
+
+ def setx(self, value):
+ """
+ >>> c = C() # 10
+ >>> c.x = 12 # 11
+ >>> print c.x # 12
+ -12
+ """
+ self._x = value
+
+ x = property(getx, setx, doc="""\
+ >>> c = C() # 13
+ >>> c.x = 12 # 14
+ >>> print c.x # 15
+ -12
+ """)
+
+ def statm():
+ """
+ A static method.
+
+ >>> print C.statm() # 16
+ 666
+ >>> print C().statm() # 17
+ 666
+ """
+ return 666
+
+ statm = staticmethod(statm)
+
+ def clsm(cls, val):
+ """
+ A class method.
+
+ >>> print C.clsm(22) # 18
+ 22
+ >>> print C().clsm(22) # 19
+ 22
+ """
+ return 22
+
+ clsm = classmethod(clsm)
+
+def test_main():
+ import test_doctest2
+ # XXX 2 class docstrings are skipped.
+ # EXPECTED = 19
+ EXPECTED = 17
+ f, t = test_support.run_doctest(test_doctest2)
+ if t != EXPECTED:
+ raise test_support.TestFailed("expected %d tests to run, not %d" %
+ (EXPECTED, t))
+
+# Pollute the namespace with a bunch of imported functions and classes,
+# to make sure they don't get tested.
+from doctest import *
+
+if __name__ == '__main__':
+ test_main()