Doctest Options: Understanding Their Usage

Today we’re going to talk about doctests those handy little snippets that help us test our code without having to write a bunch of boilerplate tests. But let’s not get too excited just yet, because as with any tool in programming, there are options involved. And let’s face it, options can be confusing and overwhelming.

But don’t let it rattle you! We’re here to break down the doctest options into simple terms that even a caveman could understand (or at least a Python beginner). So grab your favorite snack and let’s get started!

First off, what are these mysterious “doctests” we speak of? Well, they’re essentially code examples with expected output. You can think of them as little mini-tests that run automatically when you execute your script or module. They look like this:

# This function adds two numbers together and returns the result
def add_numbers(x, y):
    """Add two numbers together."""
    return x + y

# This is a doctest, which is a code example with expected output
# It serves as a mini-test that runs automatically when the script is executed
# The expected output for this doctest is 5, which is the result of adding 2 and 3
> add_numbers(2, 3)
5

The first line is a docstring (documentation string), which provides some context for the function. The second line starts with three double-quotes and ends with a newline this tells Python to treat it as an interactive input/output example. When you run your script, doctest will execute that code snippet and compare its output to what’s expected (in this case, 5).

Now those ***** options we mentioned earlier. There are a few different ones, but for the sake of simplicity, we’ll focus on two: `+NORMALIZE_WHITESPACE` and `-ELLIPSIS`.

The first option, `+NORMALIZE_WHITESPACE`, tells doctest to ignore any whitespace differences between your expected output and what it actually gets. This is useful if you’re dealing with formatted text or string literals that might have different line breaks or indentation than what’s in the example. For instance:

# Define a function called format_string that takes in a string as input
def format_string(text):
    """Format a string using f-strings."""
    # Use f-string formatting to insert the input string into a greeting
    return f"Hello, {text}!"

# Call the format_string function with the input "world" and print the result
> format_string("world")
'Hello, world!'

If you run this doctest with `+NORMALIZE_WHITESPACE`, it will ignore any whitespace differences between the expected output and what’s actually returned. This can be helpful if your formatted text has different line breaks or indentation than what’s in the example, but still produces the same result.

The second option we mentioned is `-ELLIPSIS`. This tells doctest to ignore any trailing ellipsis (`…`) that might appear at the end of a string literal. For instance:

# This function generates a random string of a given length
def get_string(length):
    """Return a random string with the given length."""
    import secrets # Importing the secrets module to generate random strings
    from string import ascii_letters, digits # Importing the ascii_letters and digits from the string module
    
    # Using a list comprehension to generate a string of random characters with the given length
    # secrets.choice() randomly selects a character from the given string of ascii_letters and digits
    # The for loop runs for the given length, adding a random character to the string each time
    return ''.join(secrets.choice(ascii_letters + digits) for _ in range(length))

# Calling the function with a length of 10 and printing the result
> get_string(10)
'9j6m5c7qxk'

If you run this doctest with `-ELLIPSIS`, it will ignore any trailing ellipsis that might appear at the end of the string literal. This can be helpful if your function returns a long string or list, but still produces the same result as what’s expected in the example.

And there you have it! Doctest options demystified. Remember to use them sparingly and only when necessary they should enhance your tests, not replace them entirely.

But wait, did we mention that doctests can also be debugged? Yes, indeed! Doctest provides several mechanisms for debugging doctest examples:

* Several functions convert doctests to executable Python programs, which can be run under the Python debugger, “pdb”. This is especially useful when you’re trying to figure out why a particular test is failing.

Doctest options and debugging mechanisms demystified.

SICORPS