Is there way to only perform the doctests, ignoring print function calls?

时光总嘲笑我的痴心妄想 提交于 2019-12-11 03:52:54

问题


Hypothetically speaking, my function returns a value and has lot of print statements (maybe 100 or more).

Is there a way to run doctest such that all the other printing work can be ignored/skipped (I am familiar with the +SKIP directive, which is for skipping doctest examples), i.e. when I execute my function (or run my module as a script) with doctests:

python mymodule.py

Or:

python -m doctest mymodule.py

I should get:

  • nothing, in case of success; or
  • error messages in case any test example fails;

and nothing else. Running doctest should not give me a terminal window full of outputs / text from those print function calls.

Please don't suggest using unit testing (e.g. unittest) as it'll kill the essence of the question.


回答1:


doctest uses stdout, not stderr, to show messages from any failing tests. Therefore you cannot patch out stdout as this answer originally suggested - this will suppress your print calls and any messages from doctest.


One option is to define functions that print with an additional verbose parameter, so that you can suppress this when necessary.

def foo(verbose=True):
    """Does whatever.

        >>> foo(verbose=False)

    """
    if verbose:
        print('Hello world')

Although you have to change the functions, this also gives you useful options when not testing.


Another is to explicitly supply the appropriate print function to the functions that use it, allowing you to pass a NOOP at runtime:

def bar(print=print):
    """Does whatever.

        >>> bar(print=lambda *args, **kwargs: None)

    """
    print('Hello world')

This also requires changes to function definitions, but at least avoids changes in the bodies of those functions.


A third option is to patch out print for the whole module under test, for example:

def baz():
    """Does whatever.

        >>> baz()

    """
    print('Hello world')

if __name__ == '__main__':

    import doctest

    print = lambda *args, **kwargs: None

    doctest.testmod()

Note that this affects the outputs that doctest sees, too, so you don't include any of the print output in the docstring (I assume this is good news!) It won't work with python -m doctest mymodule.py, though.




回答2:


in addition to jonrsharpe's excellent answer, there is one more way, that does work with the python3 -m doctest module.py construct.

#!/usr/bin/python3 -OO
'''
Some ideas for adding additional verbosity during doctest, and for
reducing verbosity and startup delays during doctest or pydoc.
'''
from __future__ import print_function  # for compatibility with python2
import sys, os, logging
logging.basicConfig(level = logging.DEBUG if __debug__ else logging.INFO)
COMMAND = os.path.splitext(os.path.basename(sys.argv[0]))[0]
if COMMAND in ['doctest', 'pydoc']:
    NONDOCTESTPRINT = lambda *args, **kwargs: None
    DOCTESTDEBUG = logging.debug
else:
    NONDOCTESTPRINT = print
    DOCTESTDEBUG = lambda *args, **kwargs: None
    # You can also use this `else` block to import things not needed during
    # doctest, especially slow-loading modules like `requests`,
    # or to do some other verbose or slow initialization.

def test(string):
    '''
    print string after lead-in

    >>> test("I'm in love with you!")
    Listen!
    I'm in love with you!
    '''
    DOCTESTDEBUG("If this works, you shouldn't see anything but this")
    print('Listen!')
    NONDOCTESTPRINT('Do you want to know a secret?')
    NONDOCTESTPRINT('Do you promise not to tell? Whoa, oh...')
    NONDOCTESTPRINT('Closer...')
    NONDOCTESTPRINT('Let me whisper in your ear...')
    NONDOCTESTPRINT('Say the words you long to hear...')
    print(string)

if __name__ == '__main__':
    test(' '.join(sys.argv[1:]) or 'Taxation is theft.')

Here is what the output looks like, depending on how it's called.

jcomeau@aspire:/tmp$ python3 -m doctest doctesttest.py 
DEBUG:root:If this works, you shouldn't see anything but this
jcomeau@aspire:/tmp$ python3 doctesttest.py This is a test!
Listen!
Do you want to know a secret?
Do you promise not to tell? Whoa, oh...
Closer...
Let me whisper in your ear...
Say the words you long to hear...
This is a test!

and for pydoc doctesttest:



来源:https://stackoverflow.com/questions/29696944/is-there-way-to-only-perform-the-doctests-ignoring-print-function-calls

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!