Doctest of function with random output

107 Views Asked by At

I have a function that prints a somewhat random string to the console, for example:

from random import choice

def hello():
    print(f"Hello {choice(('Guido', 'Raymond'))}!")

Please note that my actual function is more complicated than this. The random part is a request to a database that can either succeed or fail. This means that I cannot initialize a seed to have a constant outcome.

What I have tried is to use the ellipsis, but I also need to add an ugly comment for doctest to recognize it.

def hello():
    """
    >>> hello()  # doctest: +ELLIPSIS
    Hello ...!
    """
    print(f"Hello {choice(('Guido', 'Raymond'))}!")

Is there a better strategy in this situation?

For example, instead of an ellipsis it would be great if I could test that the answer is one between Hello Guido! and Hello Raymond!.

1

There are 1 best solutions below

0
wjandrea On BEST ANSWER

You could use regex: Hello followed by either Guido or Raymond followed by an exclamation point and newline: Hello (Guido|Raymond)!\n

However, capturing the stdout and running the regex is a lot of noise for a doctest. So instead, it'd be better to give an example in the docstring but skip testing it, and use a different test system, like pytest, which has a builtin way to capture stdout. For example:

from random import choice

def hello():
    """
    >>> hello()  # doctest: +SKIP
    Hello Raymond!
    """
    print(f"Hello {choice(('Guido', 'Raymond'))}!")
import re

def test_hello(capsys):
    hello()
    captured = capsys.readouterr()
    assert re.fullmatch(r'Hello (Guido|Raymond)!\n', captured.out)