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