Adam Johnson

Home | Blog | Training | Projects | Colophon | Contact

Why does Python log a SyntaxWarning saying "assertion is always true"?

2020-06-18 Wiggle wiggle

Take this code:

def test_equality():
    number = 123
    assert (number == 456, "Number was not 456")

If we import its containing module, we’ll see a warning message on line 3:

>>> import example
/.../example.py:3: SyntaxWarning: assertion is always true, perhaps remove parentheses?
  assert (number == 456, "Number was not 456")

This warning says that our test will pass, even though it should fail since number is 123, not 456. Indeed, if we run the function, it passes silently:

>>> example.test_equality()
>>>

Python emits the SyntaxWarning at import time because it can predict that the assertion will always pass. So why is this the case?

assert is a conditional statement, like if or while. This means it doesn’t take parentheses around its arguments. In our code, we’ve used parentheses, which are being parsed as a tuple of two elements instead.

Our code is effectively the same as this:

def test_equality():
    number = 123
    a_tuple = (number == 456, "Number was not 456")
    assert a_tuple

Tuples are truthy (convert to True in checks) if they contain any elements. Our tuple contains two elements, so it’s always truthy, regardless of whether the equality check in the first element is True or False.

The solution is to follow the warning message and remove the parentheses from the original code:

def test_equality():
    number = 123
    assert number == 456, "Number was not 456"

Now Python sees the two elements as the arguments to assert. Running the code produces the expected error:

>>> import example
>>> example.test_equality()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../example.py", line 3, in test_equality
    assert number == 456, "Number was not 456"
AssertionError: Number was not 456

Great!

Flake8

If you want to catch this error before you run your code, you can use the popular tool flake8. Its error code F631 warns about this. For example, running it against the original version of our code:

$ flake8 example.py
example.py:3:5: F631 assertion is always true, perhaps remove parentheses?

If you’re looking to improve the general quality of your Python code, running Flake8 as part of your development cycle will help.

Fin

I hope this helps you understand and fix this error,

—Adam


Are your Django project's tests slow? Read Speed Up Your Django Tests now!


Subscribe via RSS, Twitter, or email:

One summary email a week, no spam, I pinky promise.

Related posts:

Tags: python