Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Line continuation/wrapping in doctest

Tags:

python

doctest

I am using doctest.testmod() to do some basic testing. I have a function that returns a long string, say get_string(). Something like:

def get_string(a, b):
    r''' (a, b) -> c

    >>> get_string(1, 2)
    'This is \n\n a long \n string with new \
    space characters \n\n'
    # Doctest should work but does not.

    '''
    return ('This is \n\n a long \n string ' + \
            'with new space characters \n\n')

The problem is that the doctest is not passing because it is expecting a single line string, and it is treating the wrap as a \n character. Is there a way to get around this?

PS: This is not the actual function I am working with, but a minimal version for your sake.

like image 253
JCOC611 Avatar asked Mar 02 '15 08:03

JCOC611


3 Answers

You can use NORMALIZE_WHITESPACE option (see also full list of options).

Here is an example from doctest documentation:

>>> print range(20) # doctest: +NORMALIZE_WHITESPACE
[0,   1,  2,  3,  4,  5,  6,  7,  8,  9,
10,  11, 12, 13, 14, 15, 16, 17, 18, 19]
like image 197
geekQ Avatar answered Nov 15 '22 21:11

geekQ


I don't think you understood how doctest works. It does not check whether the output is somehow "equivalent", it only checks if the output is identical (with only very minor possible variations, like using ellipsis). From the documentation:

The doctest module searches for pieces of text that look like interactive Python sessions, and then executes those sessions to verify that they work exactly as shown.

Doctest matches the output (not a string literal, a python expression or whatever. Raw output bytes) with the content of the sample output you provide. Since it doesn't know that the text between quotes represents a string literal it cannot interpret it as you want.

In other words: the only thing you can do is to simply put the whole output on one line as in:

>>> get_string(1, 2)
    'This is \n\n a long \n string with new space characters \n\n'

If the output of this is too long you can try to modify the example to produce a shorter string (e.g. cutting it to 50 characters: get_string(1, 2)[:50]). If you look at doctests of different projects you'll find different hacks to make doctests more readable while providing reliable output.

like image 22
Bakuriu Avatar answered Nov 15 '22 21:11

Bakuriu


If you are making a test against a long single-line string in the output, you can keep the doctest match string within 80 characters for PEP8 goodness by using doctest's ELLIPSIS feature, where ... will match any string. While it is generally used for variable output like object addresses, it works just fine with (long) fixed output as well, for example:

def get_string(a, b):
    r''' (a, b) -> c

    >>> get_string(1, 2)  # doctest: +ELLIPSIS
    'This is ... string with newline characters \n\n'
    '''
    return ('This is \n\n a long \n string '
            'with newline characters \n\n')

There is a small loss of exactness in the matching, but this is usually not critical for tests.

like image 44
Alex Dupuy Avatar answered Nov 15 '22 21:11

Alex Dupuy