Python’s assert statement allows you to write sanity checks in your code. These checks are known as assertions, and you can use them to test if certain assumptions remain true while you’re developing your code. If any of your assertions turn false, it indicates a bug by raising an AssertionError.
Assertions are a convenient tool for documenting, debugging, and testing code during development. Once you’ve debugged and tested your code with the help of assertions, then you can turn them off to optimize the code for production. You disable assertions by running Python in optimized mode with the -O or -OO options, or by setting the PYTHONOPTIMIZE environment variable.
By the end of this tutorial, you’ll understand that:
assertin Python is a statement for setting sanity checks in your code.assert()checks a condition and raises anAssertionErrorif false.- You should use asserts for debugging and testing, not for data validation or error handling.
raiseandassertare different becauseraisemanually triggers an exception, whileassertchecks a condition and raises an exception automatically if the condition fails.
To get the most out of this tutorial, you should have previous knowledge of expressions and operators, functions, conditional statements, and exceptions. Having a basic understanding of documenting, debugging, and testing Python code is also a plus.
Delve into the tutorial to learn how to effectively use assertions for documenting, debugging, and testing your Python code, along with understanding their limitations and best practices for production environments.
Free Download: Get a sample chapter from Python Tricks: The Book that shows you Python’s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.
Take the Quiz: Test your knowledge with our interactive “Python's assert: Debug and Test Your Code Like a Pro” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
Python's assert: Debug and Test Your Code Like a ProTest your understanding of Python's assert statement. Learn when to use assertions for debugging, testing, and documenting your code.
Getting to Know Assertions in Python
Python implements a feature called assertions that’s pretty useful during the development of your applications and projects. You’ll find this feature in several other languages too, such as C and Java, and it comes in handy for documenting, debugging, and testing your code.
If you’re looking for a tool to strengthen your debugging and testing process, then assertions are for you. In this section, you’ll learn the basics of assertions, including what they are, what they’re good for, and when you shouldn’t use them in your code.
What Are Assertions?
In Python, assertions are statements that you can use to set sanity checks during the development process. Assertions allow you to test the correctness of your code by checking if some specific conditions remain true, which can come in handy while you’re debugging code.
The assertion condition should always be true unless you have a bug in your program. If the condition turns out to be false, then the assertion raises an exception and terminates the execution of your program.
With assertions, you can set checks to make sure that invariants within your code stay invariant. By doing so, you can check assumptions like preconditions and postconditions. For example, you can test conditions along the lines of This argument is not None or This return value is a string. These kinds of checks can help you catch errors as soon as possible when you’re developing a program.
What Are Assertions Good For?
Assertions are mainly for debugging. They’ll help you ensure that you don’t introduce new bugs while adding features and fixing other bugs in your code. However, they can have other interesting use cases within your development process. These use cases include documenting and testing your code.
The primary role of assertions is to trigger the alarms when a bug appears in a program. In this context, assertions mean Make sure that this condition remains true. Otherwise, throw an error.
In practice, you can use assertions to check preconditions and postconditions in your programs at development time. For example, programmers often place assertions at the beginning of functions to check if the input is valid (preconditions). Programmers also place assertions before functions’ return values to check if the output is valid (postconditions).
Assertions make it clear that you want to check if a given condition is and remains true. In Python, they can also include an optional message to unambiguously describe the error or problem at hand. That’s why they’re also an efficient tool for documenting code. In this context, their main advantage is their ability to take concrete action instead of being passive, as comments and docstrings are.
Finally, assertions are also ideal for writing test cases in your code. You can write concise and to-the-point test cases because assertions provide a quick way to check if a given condition is met or not, which defines if the test passes or not.
You’ll learn more about these common use cases of assertions later in this tutorial. Now you’ll learn the basics of when you shouldn’t use assertions.
When Not to Use Assertions?
In general, you shouldn’t use assertions for data processing or data validation, because you can disable assertions in your production code, which ends up removing all your assertion-based processing and validation code. Using assertions for data processing and validation is a common pitfall, as you’ll learn in Understanding Common Pitfalls of assert later in this tutorial.
Additionally, assertions aren’t an error-handling tool. The ultimate purpose of assertions isn’t to handle errors in production but to notify you during development so that you can fix them. In this regard, you shouldn’t write code that catches assertion errors using a regular try … except statement.
Understanding Python’s assert Statements
Now you know what assertions are, what they’re good for, and when you shouldn’t use them in your code. It’s time to learn the basics of writing your own assertions. First, note that Python implements assertions as a statement with the assert keyword rather than as a function. This behavior can be a common source of confusion and issues, as you’ll learn later in this tutorial.
In this section, you’ll learn the basics of using the assert statement to introduce assertions in your code. You’ll study the syntax of the assert statement. Most importantly, you’ll understand how this statement works in Python. Finally, you’ll also learn the basics of the AssertionError exception.
The Syntax of the assert Statement
An assert statement consists of the assert keyword, the expression or condition to test, and an optional message. The condition is supposed to always be true. If the assertion condition is true, then nothing happens, and your program continues its normal execution. On the other hand, if the condition becomes false, then assert halts the program by raising an AssertionError.
In Python, assert is a simple statement with the following syntax:
assert expression[, assertion_message]
Here, expression can be any valid Python expression or object, which is then tested for truthiness. If expression is false, then the statement throws an AssertionError. The assertion_message parameter is optional but encouraged. It can hold a string describing the issue that the statement is supposed to catch.
Here’s how this statement works in practice:
>>> number = 42
>>> assert number > 0
>>> number = -42
>>> assert number > 0
Traceback (most recent call last):
...
AssertionError
With a truthy expression, the assertion succeeds, and nothing happens. In that case, your program continues its normal execution. In contrast, a falsy expression makes the assertion fail, raising an AssertionError and breaking the program’s execution.
To make your assert statements clear to other developers, you should add a descriptive assertion message:
>>> number = 42
>>> assert number > 0, f"number greater than 0 expected, got: {number}"
>>> number = -42
>>> assert number > 0, f"number greater than 0 expected, got: {number}"
Traceback (most recent call last):
...
AssertionError: number greater than 0 expected, got: -42
The message in this assertion clearly states which condition should be true and what is making that condition fail. Note that the assertion_message argument to assert is optional. However, it can help you better understand the condition under test and figure out the problem that you’re facing.
So, whenever you use assert, it’s a good idea to use a descriptive assertion message for the traceback of the AssertionError exception.
An important point regarding the assert syntax is that this statement doesn’t require a pair of parentheses to group the expression and the optional message. In Python, assert is a statement instead of a function. Using a pair of parentheses can lead to unexpected behaviors.
For example, an assertion like the following will raise a SyntaxWarning:
>>> number = 42
>>> assert(number > 0, f"number greater than 0 expected, got: {number}")
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
This warning has to do with non-empty tuples always being truthy in Python. In this example, the parentheses turn the assertion expression and message into a two-item tuple, which always evaluates to true.
Fortunately, recent versions of Python throw a SyntaxWarning to alert you of this misleading syntax. However, in older versions of the language, an assert statement like the one above will always succeed.
This issue often appears when you’re using long expressions or messages that take more than a single line. In these cases, the parentheses are the natural way to format the code, and you may end up with something like the following:
number = 42
assert (
number > 0 and isinstance(number, int),
f"number greater than 0 expected, got: {number}"
)
Using a pair of parentheses to split a long line into multiple lines is a common formatting practice in Python code. However, in the context of an assert statement, the parentheses turn the assertion expression and message into a two-item tuple.
In practice, if you want to split a long assertion into several lines, then you can use the backslash character (\) for explicit line joining:
number = 42
assert number > 0 and isinstance(number, int), \
f"number greater than 0 expected, got: {number}"
The backslash at the end of first line of this assertion joins the assertion’s two physical lines into a single logical line. This way, you can have appropriate line length without the risk of a warning or a logical error in your code.
Note: PEP 679 was created on January 7, 2022, and is proposing to allow parentheses around the assertion expression and message. If the PEP gets approved and implemented, then the issue of accidental tuples won’t affect Python code in the future.
There’s an edge case of this parentheses-related issue. If you provide only the assertion expression in parentheses, then assert will work just fine:
>>> number = 42
>>> assert(number > 0)
>>> number = -42
>>> assert(number > 0)
Traceback (most recent call last):
...
AssertionError
Why is this happening? To create a single-item tuple, you need to place a comma after the item itself. In the code above, the parentheses by themselves don’t create a tuple. That’s why the interpreter ignores the parentheses, and assert works as expected.
Even though the parentheses seem to work in the scenario described in the above example, it’s not a recommended practice. You can end up shooting yourself in the foot.
The AssertionError Exception
If the condition of an assert statement evaluates to false, then assert raises an AssertionError. If you provide the optional assertion message, then this message is internally used as an argument to the AssertionError class. Either way, the raised exception breaks your program’s execution.
Most of the time, you won’t raise AssertionError exceptions explicitly in your code. The assert statement takes care of raising this exception when the assertion condition fails. Additionally, you shouldn’t attempt to handle errors by writing code that catches the AssertionError exception, as you’ll learn later in this tutorial.
Finally, AssertionError is a built-in exception that inherits from the Exception class and is considered a concrete exception that should be raised instead of subclassed.
That’s it! Now you know the basics of the assert statement. You’ve learned the statement’s syntax, how assert works in practice, and also what the main characteristics of the AssertionError exception are. It’s time to move forward and explore some effective and common ways to write assertions in Python.
Exploring Common Assertion Formats
When it comes to writing the assert statement, you’ll find several assertion formats that are common in Python code. Being aware of these formats will allow you to write better assertions.
The following examples showcase a few of these common assertion formats, starting with assertions that compare objects:
>>> # Comparison assertions
>>> assert 3 > 2
>>> assert 3 == 2
Traceback (most recent call last):
...
AssertionError
>>> assert 3 > 2 and 5 < 10
>>> assert 3 == 2 or 5 > 10
Traceback (most recent call last):
...
AssertionError
Comparison assertions are intended to test conditions that compare two or more objects using comparison operators. These assertions can also include compound expressions based on Boolean operators.
Another common assertion format is related to membership tests:
>>> # Membership assertions
>>> numbers = [1, 2, 3, 4, 5]
>>> assert 4 in numbers
>>> assert 10 in numbers
Traceback (most recent call last):
...
AssertionError
Membership assertions allow you to check if a given item is present in a specific collection, such as a list, tuple, set, dictionary, or the like. These assertions use the membership operators,