Doctests and decorated methods don't get along

Terry Reedy tjreedy at udel.edu
Sat Feb 6 14:39:00 EST 2010


On 2/6/2010 6:48 AM, Steven D'Aprano wrote:
> It seems that doctest doesn't discover or execute doctests in methods
> which have been decorated.
>
>
> Here is my test file:
>
> # ======
> class MyStaticMethod(object):
>      """Emulate built-in staticmethod descriptor."""
>      def __init__(self, f):
>          self.f = f
>      def __get__(self, obj, objtype=None):
>          return self.f
>
> class Test(object):
>      def method1(self):
>          """Doc string
>
>          >>>  print 'x'
>          x
>          """
>
>      @staticmethod
>      def method2():
>          """Doc string
>
>          >>>  print 'y'
>          y
>          """
>
>      @MyStaticMethod
>      def method3():
>          """Doc string
>
>          >>>  print '***'  # This test should fail.
>          z
>          """
>
> if __name__ == '__main__':
>      import doctest
>      doctest.testmod(verbose=True)
> # ======
>
>
> and here is the output using Python 2.6.4:
>
> [steve at sylar python]$ python2.6 test_doctests.py
> Trying:
>      print 'x'
> Expecting:
>      x
> ok
> Trying:
>      print 'y'
> Expecting:
>      y
> ok
> 5 items had no tests:
>      __main__
>      __main__.MyStaticMethod
>      __main__.MyStaticMethod.__get__
>      __main__.MyStaticMethod.__init__
>      __main__.Test
> 2 items passed all tests:
>     1 tests in __main__.Test.method1
>     1 tests in __main__.Test.method2
> 2 tests in 7 items.
> 2 passed and 0 failed.
> Test passed.
>
>
> It doesn't even see method3, let alone run the tests.

Method3 is wrapped as an instance of MyStaticMethod and doctest does not 
see that as function. Even if it did, you would might have to copy the 
docstring (self.__doc__ = f.__doc__) to have the test run.

Note the following: (3.1)

 >>> Test.method3
<function method3 at 0x00F5F7C8>
 >>> Test.__dict__['method3']
<__main__.MyStaticMethod object at 0x00F5CDF0>
 >>> Test.__dict__['method2']
<staticmethod object at 0x00F5C290>

Doctest has to scan the dict, so it does not see the attribute-lookup 
result.

> This looks like  bug to me. Have I missed anything?

I would call it a limitation as I do not see the doc as promising 
otherwise. I believe doctest predates the descripter protocol, at least 
in its current form, so it may not be completely descriptor-aware. You 
certainly could file a feature request for improved recognition and 
subsequent calling of __get__. An initial patch would improve chances of 
action.

 > Any workarounds?

Perhaps look at the doctest source to see why staticmethod instances are 
recognized as functions.

If doctest directly special-cases their recognition, then use the 
standard nested function approach for decorators, making sure to copy 
the doc string. Look at functools.wraps.

If doctest recognizes them by some characteristic that you have not 
emulated, try to improve that.

Terry Jan Reedy


Terry Jan Reedy




More information about the Python-list mailing list