You are currently viewing Understanding assert For Debugging In Python

Understanding assert For Debugging In Python

Python’s assert statements are one of several options for debugging code in Python.

Python’s assert is mainly used for debugging by allowing us to write sanity tests in our code. These tests are performed to ensure that a particular condition is True or False. If the condition is False, an AssertionError is raised, indicating that the test condition failed.

Understanding assert

Python’s assert keyword is used to write assert statements that contain a condition or assumption that is tested against the condition from the program that we expect to be true.

If the condition matches the expected condition, nothing is displayed on the console and the execution continues, otherwise, an AssertionError is displayed. This exception interrupts program execution and indicates that the condition test failed.

Syntax

The syntax of the assert statement is written in the following form:

assert [condition], [error message]

condition – the condition or assumption to be tested

error message – the error message we want to display in the console when the condition is failed.

The assert In Action

Let’s create some assert statements to perform code checks. Consider the following example, in which we are testing our program to see if it produces the expected results.

The above code defines a function called evaluate_num that takes a parameter num. The function checks if the value of num is greater than 5. If it is, the function returns the square of num (num * num). Otherwise, if num is less than or equal to 5, the function returns num multiplied by 2 (num * 2).

The assert statement checks whether the variable val is equal to 10 after evaluating evaluate_num(5). In this case, evaluate_num(5) returns 10, which means that the assert statement is true and we’ll get nothing in the console.

Let’s see what happens when we pass a num greater than 5.

We called the evaluate_num with the argument 6. Since 6 is greater than 5, the function will square the number 6 (6 * 6) which makes the variable val equal to 36, which makes our assert statement false. As a result, we’ll get an AssertionError with the message "Condition failed.".

Controlling the Behavior of assert

We were able to write assertions in a single line by using the assert keyword, and this single-line assert statements are equivalent to the following expression:

The above if __debug__ conditional would function similarly to the assert statement written in the preceding code.

As a result of the above expression, the syntax of the if __debug__ conditional would be:

__debug__

What exactly is __debug__, and how does it affect the behavior of assert statements in a Python program?

The __debug__ is a built-in constant in Python that is set to True by default. However, we can change this to False by running Python in optimized mode with the -O command line option or by modifying the PYTHONOPTIMIZE variable.

As we can see when we printed the __debug__, we got True which indicates that our Python is not running in optimized mode.

Let’s understand better with examples.

The above code defines the Shopping class, which has a __init__ method that takes two parameters, product and price. These parameters’ values are assigned to the instance variables self.product and self.price.

This class has another method called list that returns product information along with a price. This method includes an assert statement that determines whether the product’s price is greater than 0.

Then we created three instances of the Shopping class (item_1item_2, and item_3) and passed in the various products and prices. When we run the above code, we get the following result.

The first two instances passed the test because the assert statement condition (self.price > 0) was met. As a result, we received the string, whereas in the third case, the price was set to -35, which did not satisfy the assert statement condition, and we received the AssertionError with the error message.

The following if __debug__ conditional is equivalent to the assert statement we created in the method list within the class Shopping. If we had used the following code instead of the assert statement in the above code, the code would have worked perfectly.

Disabling Assertions

We can disable the assertion and prevent the AssertionError message from being displayed on the console. We’ll try it manually first, then look at other safe options.

We could disable the assertion manually if we set __debug__ to False. Let’s see if we can complete this task within our program.

Within our method list, we added a code snippet that checks the value of __debug__, if __debug__ is set to False, it means that Python is running in optimized mode and the assertions are disabled.

Since assertions are disabled, the above code will produce no errors on the console.

Note: This is not a good practice and is not recommended method to disable assertions.

The -O Option

The -O flag is a command-line option that disables all assertions. Internally, this option sets the __debug__ constant to False.

Open the terminal and change the directory containing the Python file and run the following command:

The python -O test.py command enables the optimized mode and executes the Python file test.py. The -O flag instructs the Python interpreter to optimize the code by turning off assertions.

We would have gotten the AssertionError if we hadn’t used the -O flag.

PYTHONOPTIMIZE Env Variable

By setting the PYTHONOPTIMIZE environment variable to 1, we can run Python in optimized mode.

To set PYTHONOPTIMIZE=1, enter the following command in the terminal. This command will automatically run Python in optimized mode.

When we check the status of the __debug__ constant in the Python shell, it is automatically set to False.

To undo the optimized mode, use the command set PYTHONOPTIMIZE=0.

Performing Debugging

In this section, we’ll write a bunch of assert statements and then test them with pytest, a third-party package. This package contains a simpler syntax for writing tests.

Since this is an external package, we must install it by running the command pip install pytest in the terminal.

Make a Python file called test_file.py and place the following code, which includes tests, inside it.

Now, open a terminal, navigate to the directory containing the Python file test_file.py, and type pytest test_file.py.

The output of our tests produced by pytest is shown above, and we can see that three of them failed and three passed. The output provided full details for the three failed tests.

Note: pytest collects tests based on a naming convention. By default, classes containing tests must begin with Test, and any function in a file that should be treated as a test must also begin with test_pytest will run all files of the form test_*.py or *_test.py in the current directory and its subdirectories. More details on the naming convention.

Conclusion

assert is a built-in keyword in Python that is used to create assert statements that perform sanity checks in our code. It is used for testing and debugging.

The assert statement includes a condition that is used to determine whether the condition is True or False. If the condition is False, an AssertionError is thrown, indicating that the condition was not met.

Let’s recall what we’ve learned:

  • What is an assert statement with an example?
  • __debug__ constant in Python.
  • Controlling the behavior of assert statements.
  • Disabling assertions using the -O option and PYTHONOPTIMIZE environment variable.
  • Debugging code using the pytest package.

πŸ†Other articles you might be interested in if you liked this one

βœ…Python generators and the yield keyword – how they work?

βœ…Performing high-level path operations using pathlib in Python.

βœ…Understanding the different uses of asterisk(*) in Python.

βœ…What is the difference between seek() and tell() in Python?

βœ…Generate temporary files and directories using tempfile module in Python.

βœ…How to change the string representation of the objects in Python?

βœ…__init__ and __new__: The concept of initializer and constructor in Python.

βœ…What are context managers in Python?


That’s all for now

Keep Coding✌✌