Use unittest.mock to Monitor Calls
In this step, we'll explore how to use the unittest.mock module to monitor function calls. The unittest.mock module is a powerful tool for testing and debugging, and it provides a convenient way to track function invocations, arguments, and return values.
Let's continue with the greet function from the previous steps. We'll use unittest.mock to monitor the calls to greet.
Modify the my_function.py file in the ~/project directory to include the following code:
## ~/project/my_function.py
from unittest import mock
def greet(name):
"""This function greets the person passed in as a parameter."""
print(f"Hello, {name}!")
## Create a mock object for the greet function
mock_greet = mock.Mock(wraps=greet)
## Example usage
mock_greet("Alice")
mock_greet("Bob")
## Print the number of times the function was called
print(f"The greet function was called {mock_greet.call_count} times.")
## Print the arguments the function was called with
print(f"The calls were: {mock_greet.call_args_list}")
In this code:
- We import the
mock module from unittest.
- We create a
mock.Mock object that wraps the greet function. The wraps argument tells the mock object to call the original greet function when it's called.
- We then call the
mock_greet object instead of the original greet function.
- Finally, we use the
call_count and call_args_list attributes of the mock object to get information about the function calls.
Run the script again using the same command:
python ~/project/my_function.py
You should see output similar to this:
Hello, Alice!
Hello, Bob!
The greet function was called 2 times.
The calls were: [call('Alice'), call('Bob')]
This output shows that the greet function was called twice, and it also shows the arguments that were passed to the function in each call.
Now, let's examine the call_args_list more closely. It's a list of call objects, each representing a single call to the mocked function. You can access the arguments of each call using the args and kwargs attributes of the call object.
For example, let's modify the code to print the arguments of the first call:
## ~/project/my_function.py
from unittest import mock
def greet(name):
"""This function greets the person passed in as a parameter."""
print(f"Hello, {name}!")
## Create a mock object for the greet function
mock_greet = mock.Mock(wraps=greet)
## Example usage
mock_greet("Alice")
mock_greet("Bob")
## Print the number of times the function was called
print(f"The greet function was called {mock_greet.call_count} times.")
## Print the arguments the function was called with
print(f"The calls were: {mock_greet.call_args_list}")
## Print the arguments of the first call
if mock_greet.call_args_list:
print(f"The arguments of the first call were: {mock_greet.call_args_list[0].args}")
Run the script again:
python ~/project/my_function.py
You should see output similar to this:
Hello, Alice!
Hello, Bob!
The greet function was called 2 times.
The calls were: [call('Alice'), call('Bob')]
The arguments of the first call were: ('Alice',)
This output shows that the first call to greet was made with the argument "Alice".
The unittest.mock module provides a powerful and flexible way to monitor function calls in Python. It's a valuable tool for testing, debugging, and performance analysis.