Python Doctest Module Tutorial – Complete Guide

Python is a versatile language loved by millions of developers worldwide. It has wide use-cases and can be employed for developing almost anything, thanks to its comprehensive set of libraries. However, testing during development is one area that doesn’t get enough attention and that’s exactly what we’ll explore today, with a specific focus on Python’s doctest module.

Understanding the doctest Module

The doctest module in Python allows programmers to write test cases within the docstrings of their functions/methods, making it easier to create and understand tests. It’s part of Python’s standard utility modules, which means it comes with Python and doesn’t require additional installations.

doctest encourages the use of docstrings in your code. By writing tests in the docs, you’re not just explaining the purpose of the function/method but also verifying it with a valid test case. Additionally, doctest doesn’t disturb your regular workflow, as it allows developers to test their code right where they write it, reducing the need to switch contexts.

Learning to use doctest brings a unique advantage. It encourages the use of test-driven development (TDD), a practice where developers write tests before the actual implementation. This approach can lead to the creation of more robust and cleaner code. If you’re interested in creating well-documented and thoroughly tested code, the doctest module is undoubtedly a skill worth learning.

Now, let’s dive deeper and discover the art of testing in Python with the doctest module with some engaging coding examples. We’ve done our best to structure these in a beginner-friendly way, so let’s get started!

CTA Small Image
FREE COURSES AT ZENVA
LEARN GAME DEVELOPMENT, PYTHON AND MORE
ACCESS FOR FREE
AVAILABLE FOR A LIMITED TIME ONLY

Writing Your First Test with Python’s doctest Module

Let’s create a simple function that adds two numbers. Our goal will be to test this function using Python’s doctest module. Here’s our starter function:

def add_numbers(a, b):
    """
    This function adds two numbers.
    
    >>> add_numbers(2, 2)
    4
    """
    return a + b

The docstring under the function definition contains our test case. The “>>>” mentions the inputs, and the line just below it states the expected output.

Running the Test

To run the test, add this snippet at the end of your python script:

if __name__ == "__main__":
    import doctest
    doctest.testmod()

This part of the code tells Python to run the test module when the script is run directly from the command line.

Testing Multiple Cases

You can add as many test cases in your function docstrings as desired. In our case, let’s add a few more for the add_numbers function:

def add_numbers(a, b):
    """
    This function adds two numbers.

    >>> add_numbers(2, 2)
    4
    >>> add_numbers(-1, 1)
    0
    >>> add_numbers(4.2, 5.8)
    10.0
    """
    return a + b

The Edgecases: Testing for Errors

doctest also supports a way to check for error cases. For instance, in the add_numbers function, let’s check if it raises a TypeError when one tries to add a string to an integer:

def add_numbers(a, b):
    """
    This function adds two numbers.

    >>> add_numbers(2, 2)
    4
    >>> add_numbers("two", 2)
    Traceback (most recent call last):
        ...
    TypeError: can only concatenate str (not "int") to str
    """
    return a + b

This is super handy, because it allows us to verify that our functions are behaving as expected, even when they receive invalid data.

Using doctest with Classes

Doctest is not just limited to testing functions; it can also work well with Python classes. Let’s take an example:

class Circle:
    """
    This class creates a Circle object.
    
    >>> c = Circle(4)
    >>> c.radius
    4
    """
    
    def __init__(self, radius):
        self.radius = radius

Like before, the test case is outlined in the docstring. Here, we create a Circle object and check if it correctly assigns the radius.

Testing Instance Methods

There may be instances when your class has methods that you want to test. Luckily, doctest lets you do that. Continuing with the Circle class, let’s add a method to calculate the area:

import math

class Circle:
    """
    This class creates a Circle object.
    
    >>> c = Circle(4)
    >>> c.radius
    4
    """
    
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        """
        This method calculates the area of the circle.

        >>> c = Circle(7)
        >>> round(c.area(), 2)
        153.94
        """
        return math.pi * self.radius ** 2

We added the area method to the Circle class and put a test case in its docstring. We tested for the area of a Circle object with the radius of 7 and rounded it to 2 decimal places.

Error Handling in Classes

What if you want to check for errors in your class methods? Let’s add a method in the Circle class that raises a ValueError if the radius is not a positive number:

class Circle:
    """
    This class creates a Circle object.
    
    >>> c = Circle(4)
    >>> c.radius
    4
    """

    def __init__(self, radius):
        if radius >> c = Circle(7)
        >>> round(c.area(), 2)
        153.94
        """
        return math.pi * self.radius ** 2

    def set_radius(self, new_radius):
        """
        This method sets a new radius for the circle.

        >>> c = Circle(5)
        >>> c.set_radius(-3)
        Traceback (most recent call last):
           ...
        ValueError: Radius must be a positive number
        """
        if new_radius <= 0:
            raise ValueError("Radius must be a positive number")
        self.radius = new_radius

The set_radius method that we’ve added changes the radius of a Circle object. We’ve set a test case testing for a negative radius which, as declared in our method, should raise a ValueError.

Running the File from the Command Line

If you want to run the doctest from command line:

python -m doctest -v your_file.py

The -v flag is used to display detailed output from the doctest module. The doctest module scans the entire file for docstrings, runs tests and finally outputs the result on the console.

Where to Go Next?

Python’s doctest module is a powerful tool to learn and implement, providing a unique blend of documentation and testing that promotes best practices such as Test-Driven Development. However, mastering Python involves learning and understanding a variety of its other features as well.

Zenva’s Python Mini-Degree is a comprehensive compendium designed to give you a solid foundation in Python programming with guidance from our certified and experienced instructors. The Python Mini-Degree explores numerous Python-related topics:

  • Understanding coding basics
  • Mastering algorithms
  • Delving into object-oriented programming
  • Stepping into game and app development

You’ll learn through a hands-on, project-based approach where you’ll create your own games, algorithms, and real-world apps. This learning methodology ensures that you not only gain theoretical knowledge but also practical experience.

Also check out our broad collection of Python courses to continue your learning journey.

Conclusion

Python’s doctest module is a discrete yet powerful tool, creating an intersection of documentation and testing. This dual functionality can ramp up your productivity by enabling you to write test cases alongside code, thus enhancing the quality and reliability of your Python applications.

Mastering Python and its numerous attributes is no small feat, but it can be an enjoyable journey with the right guide. To kickstart or progress further into this journey, consider exploring the Python Mini-Degrees and other Python courses we provide at Zenva. Our engaging, project-driven courses put you in the driver’s seat of your coding education, ensuring you learn by doing – the most effective way to acquire any skill. Happy coding!

Did you come across any errors in this tutorial? Please let us know by completing this form and we’ll look into it!

FREE COURSES
Python Blog Image

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.