This rule raises an issue when the expected and actual values in an assertion appear to be inverted with respect to the testing framework’s convention.
Assertions are statements that check whether certain conditions are true. They validate that the actual results of a code snippet match the expected outcomes. By using assertions, developers can ensure that their code behaves as intended and identify potential bugs or issues early in the development process.
Python testing frameworks follow a convention for where expected and actual values should appear in assertions:
unittest, methods like assertEqual() and assertIs() compare two values passed as arguments. The
documentation commonly shows the value from the code under test first and the expected value second, for example self.assertEqual(s.split(),
['hello', 'world']). For consistency with that convention, place the actual value first and the expected value second.pytest, assertions should place the actual value on the left side and the expected value on the right side. The right-hand side
should be a literal or an identifier that represents the expected value, optionally wrapped in a helper such as pytest.approx(), rather
than a computation.assertpy, fluent assertions should place the actual value in assert_that(…) and the expected value in the
assertion method, such as .is_equal_to(…).In all of these assertion styles, the value produced by the code under test comes first and the expected value comes second. Keeping each value in the position expected by the assertion style makes the intent easier to understand and helps readers interpret failures more quickly.
Additionally, following each framework’s assertion conventions makes tests more consistent with the surrounding code and easier to read.
Having the expected value and the actual value in the wrong order will not alter the outcome of tests (they will still succeed or fail appropriately). However, the error messages will contain misleading information, making debugging more difficult.
For example, if you write self.assertEqual(0, runner.exit_code) where runner.exit_code is -1, the failure is
reported as 0 != -1. The message does not explicitly identify one value as expected and the other as actual, but following a consistent
convention still makes assertions easier to read and understand.
Swap the order of the assertion arguments so that the actual value (from the code under test) is passed as the first argument and the expected value is passed as the second argument.
import unittest
class TestRunner(unittest.TestCase):
def test_exit_code(self):
runner = Runner()
self.assertEqual(0, runner.exit_code, "Unexpected exit code") # Noncompliant
import unittest
class TestRunner(unittest.TestCase):
def test_exit_code(self):
runner = Runner()
self.assertEqual(runner.exit_code, 0, "Unexpected exit code")
In pytest, place the actual value on the left side of the assertion and the expected value on the right side. The right-hand side should be limited
to a literal or an identifier representing the expected value, including when using helpers such as pytest.approx(), rather than an
expression that computes the value.
import pytest
EXPECTED_PI = 3.14
def test_calculation():
result = perform_calculation()
assert 3.14 == result # Noncompliant
assert pytest.approx(EXPECTED_PI) == result # Noncompliant
import pytest
EXPECTED_PI = 3.14
def test_calculation():
result = perform_calculation()
assert result == 3.14
assert result == pytest.approx(EXPECTED_PI)
In assertpy, place the actual value from the code under test in assert_that(…) and pass the expected value to the
assertion method.
from assertpy import assert_that
EXPECTED_EXIT_CODE = 0
def test_exit_code():
runner = Runner()
assert_that(EXPECTED_EXIT_CODE).is_equal_to(runner.exit_code) # Noncompliant
from assertpy import assert_that
EXPECTED_EXIT_CODE = 0
def test_exit_code():
runner = Runner()
assert_that(runner.exit_code).is_equal_to(EXPECTED_EXIT_CODE)