Let’s talk about how to use Python’s built-in testing framework called doctest. Doctests are great for finding examples in docstrings and running them to make sure they work as expected. But what if you want to take things up a notch? Let’s begin exploring with the advanced features of doctest!
First off, how to use doctests with functions that have multiple input parameters or return values. For example:
# Define a function called calculate_sum that takes in two parameters, a and b
def calculate_sum(a, b):
"""Calculate the sum of two numbers and print it out."""
# Create a variable called result and assign it the value of a + b
result = a + b
# Print out a string with the sum of a and b
print("The sum is:", result)
# Return the value of result
return result
To test this function with doctest, you can add docstrings that include examples:
# Define a function called calculate_sum that takes in two parameters, a and b
def calculate_sum(a, b):
"""Calculate the sum of two numbers and print it out.
> calculate_sum(2, 3) # Example of how to use the function with expected output
The sum is: 5
> result = calculate_sum(10, 7) # Assigning the result of the function to a variable
> print("The calculated sum is:", result) # Printing the result with a custom message
"""
# Calculate the sum of a and b and assign it to a variable called sum
sum = a + b
# Print out the sum with a custom message
print("The sum is:", sum)
# Return the sum for future use
return sum
In the first example, we’re testing that when `calculate_sum()` is called with arguments of 2 and 3, it prints out “The sum is: 5”. In the second example, we’re assigning the output to a variable named `result`, which allows us to test other aspects of our function.
But what if you have functions that return multiple values? Let’s say you have this function:
# This function calculates the average of a list of numbers and prints it out, as well as returning the average and the count of numbers in the list.
def calculate_average(numbers):
"""Calculate the average of a list of numbers and print it out."""
total = sum(numbers) # calculates the sum of all numbers in the list
count = len(numbers) # counts the number of elements in the list
result = float(total) / count # calculates the average by dividing the total by the count and converting it to a float
print("The average is:", result) # prints out the average
return (result, count) # returns a tuple containing the average and the count of numbers in the list
To test this function with doctest, you can add docstrings that include examples:
# Define a function called calculate_average that takes in a list of numbers as a parameter
def calculate_average(numbers):
"""Calculate the average of a list of numbers and print it out.
> result = calculate_average([10, 20, 30]) # Example of how to use the function with a list of numbers
> print("The calculated average is:", result[0], "with", result[1], "values.") # Print out the calculated average and the number of values used to calculate it
> result = calculate_average([5, 7, 9]) # Another example of how to use the function with a different list of numbers
> print("The calculated average is:", result[0], "with", result[1], "values.") # Print out the calculated average and the number of values used to calculate it
"""
total = 0 # Initialize a variable to keep track of the sum of all the numbers in the list
for num in numbers: # Loop through each number in the list
total += num # Add the current number to the total sum
average = total / len(numbers) # Calculate the average by dividing the total sum by the number of values in the list
return (average, len(numbers)) # Return a tuple containing the calculated average and the number of values used to calculate it
In the first example, we’re testing that when `calculate_average()` is called with arguments of [10, 20, 30], it returns a tuple containing the average and the number of values. In the second example, we’re assigning this output to a variable named `result`, which allows us to test other aspects of our function.
But what if you have functions that use complex data structures or return objects? Let’s say you have this function:
# This function creates a new person object with the given name and age.
def create_person(name, age):
# Define a class named Person
class Person:
# Define the __init__ method which initializes the object with the given name and age
def __init__(self, name, age):
self.name = name
self.age = age
# Define a method named get_info which returns a string with the person's name and age
def get_info(self):
return f"{self.name} is {self.age} years old."
# Create a new instance of the Person class with the given name and age
person = Person(name, age)
# Return the person object
return person
To test this function with doctest, you can add docstrings that include examples:
def create_person(name, age): # Defines a function called "create_person" that takes in two parameters, "name" and "age"
"""Create a new person object with the given name and age.
>>> john = create_person("John Doe", 30) # Creates a new person object named "john" with the name "John Doe" and age 30
>>> print(john.get_info()) # Prints the information of the "john" object using the "get_info" method
John Doe is 30 years old.
"""
person = {} # Creates an empty dictionary to store the person's information
person["name"] = name # Assigns the "name" parameter to the "name" key in the dictionary
person["age"] = age # Assigns the "age" parameter to the "age" key in the dictionary
return person # Returns the dictionary as the person object
# The following code is not necessary as it is not used in the doctest
# However, it could be used to add more functionality to the function
# For example, adding a method to get the person's information
# def get_info(self):
# return f"{self['name']} is {self['age']} years old."
In this example, we’re testing that when `create_person()` is called with arguments of “John Doe” and 30, it returns a new object named `john`. We can then test other aspects of the returned object by calling its methods (in this case, `get_info()`) and comparing them to expected output.
And there you have it! Advanced doctesting for Python functions with multiple input parameters or return values, complex data structures, and objects.