Can python doctest ignore some output lines?
Asked Answered
M

7

44

I'd like to write a doctest like this:

"""
>>> print a.string()
          foo : a
          bar : b
         date : <I don't care about the date output>
          baz : c
"""

Is there any way to do this? I think it would make more sense to switch to unittest, but I'm curious whether it's possible to specify a range of output that shouldn't be matched for the test in doctest.

Thanks!

Miff answered 21/6, 2009 at 17:54 Comment(0)
G
50

With doctest.ELLIPSIS, you can use ... to mean "match any string here". You can set doctest options with a doctest directive, to make it active for just one test case: one example in the online docs is:

>>> print range(20) # doctest:+ELLIPSIS
[0, 1, ..., 18, 19]

If you want a doctest option to be active throughout, you can pass it as the optionflags= argument to whatever doctest functions you use, e.g. doctest.testfile. (You can pass multiple option flags there by using the | operator to bit-or them).

Garonne answered 21/6, 2009 at 18:3 Comment(5)
But how can we ignore the whole line?Ruppert
@t0ster, just put ... as the whole of the "expected output" (with doctest.ELLIPSIS set, of course), and doctest will accept any content on that output line, i.e. "ignore the whole line" of output.Garonne
"ignore the whole line" as above does not work since doctest confuses the ellipsis with a (python) continuation of the previous line. I could not find any way to ignore the whole line. Actually, I was looking for "ignore the whole output".Colvin
@RomanDolgiy and phaedrus: if you don't care about side effects, use doctest.SKIP. If you do care about side effects, then there's no great solutions, but in a separate answer below, I wrote up some ways to make it work if you really need it.Sundaysundberg
@RomanDolgiy Q: how can we ignore the whole line? A: don't print the lineFluoridation
S
20

Responding to questions about "how can we ignore the whole line": yes, the fact that "..." also looks like a continuation like makes it hard to ignore the entire output. You can use "#doctest: +SKIP" if you just want to skip the example entirely, but that won't work if you are relying on its side-effects. If you really need to do this, I suppose you could monkey-patch the doctest module itself, though I wouldn't particularly recommend it:

>>> import doctest
>>> doctest.ELLIPSIS_MARKER = '-etc-'
>>> print 12 # doctest: +ELLIPSIS
-etc-

(this test passes.)

Or you could temporarily suppress stdout and/or stderr:

>>> # Suppress stdout
>>> import sys
>>> class DevNull:
...     def noop(*args, **kwargs): pass
...     close = write = flush = writelines = noop
>>> sys.stdout = DevNull()
>>> # Run a test and ignore output (but we need its side effects)
>>> print 12 # NOTE: stdout is suppressed!
>>> # Restore stdout
>>> sys.stdout = sys.__stdout__

(this test also passes.)

Sundaysundberg answered 22/2, 2012 at 18:33 Comment(1)
Python 3 io.TextIO.write now returns the number of characters written.Fluoridation
B
15

I found it easier to simply assign the unneeded return values to a variable:

>>> _ = do_something()
>>> check_something()
True
Ballenger answered 20/3, 2014 at 15:29 Comment(0)
P
13

Ignoring the whole line is bit tricky though. Here:

"""
>>> do_your_thing() #doctest:+ELLIPSIS
...
"""

The triple dot will be interpreted as line continuation, and cause a syntax error.

If you want to ignore the whole line, you'll need something like:

"""
>>> sys.stdout.write('skip from here '); do_your_thing() #doctest:+ELLIPSIS
skip from here ...
"""
Periodontal answered 22/2, 2012 at 17:27 Comment(0)
S
8

You can write tuples before and after your function (hack inspired by answer of Mark Horvath):

def foo():
    """
    >>> ();foo();() # doctest: +ELLIPSIS
    (...)
    """
    print "Hello world"
    return "Hello world"
Suntan answered 28/10, 2015 at 20:27 Comment(1)
I like this one the most. Uses Mark's trick without needing to import another module just for doctest. Great idea!Gandhiism
S
0

Can I have an ellipsis at the beginning of the line in a Python doctest? explains how to create a custom output checker that uses an additional string as an ellipsis. This would let you write the following, while still used '...' elsewhere.

def foo():
  """
  >>> foo() # doctest: +ELLIPSIS
  [...] world
  """
  print "hello world"
Stutzman answered 1/9, 2012 at 10:39 Comment(0)
R
0

For Python3 I found it easier to just check if the outputs you want are being shown, easier to explain with an example:

def some_function():
    '''
    blah blah blah explaining function
    example:
    >>>something_you_want in some_function()
    True
    '''

super easy to implement and beginner friendly.

Rinarinaldi answered 15/12, 2023 at 15:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.