This rule raises an issue when a test file mixes both assertion argument-order conventions: some assertions put the actual value first, and others put the expected value first.
Assertions check that the code under test produces the expected results. When you write an equality assertion, one operand is the value from the code under test (the actual value) and the other is what you expect (the expected value).
Python testing frameworks commonly recommend putting the expected value second (the actual value first):
unittest, methods like assertEqual() and assertIs() take the actual value first and the expected value
second, for example self.assertEqual(s.split(), ['hello', 'world']).pytest, equality assertions place the actual value on the left and the expected value on the right, for example assert
result == 42. Helpers such as pytest.approx() wrap the expected value on the right-hand side.assertpy, fluent assertions place the actual value in assert_that(…) and the expected value in the assertion
method, such as .is_equal_to(…).This rule does not enforce that framework default. It does not raise when a file consistently uses a different order, including when every assertion puts the expected value first. It raises only when the same file mixes both orders: readers must then re-interpret each assertion, and failure messages become harder to scan.
The rule reports at most one issue per file. The primary location is the first assertion whose order can be determined. Two data flows group every order-determinable assertion in the file: one for actual-first usages and one for expected-first usages.
A true positive is a file that mixes both orders among assertions whose operands can be classified. Using an order other than the framework’s documented default is fine as long as the file is consistent. Mid-migration inconsistency is still a true positive; finish unifying or temporarily suppress the issue until the file is consistent. A false positive would mean the analyzer misclassified an operand (for example, treating a non-constant expression as expected, or the reverse), so the reported "mix" is not real.
Mixing conventions does not change whether tests pass or fail. It does make failures harder to read and slows down reviews, because each assertion must be interpreted individually instead of following one file-wide pattern.
For example, if one test writes self.assertEqual(runner.exit_code, 0) and another in the same file writes self.assertEqual(0,
runner.exit_code), both may be correct in isolation, but the file no longer has a single readable convention.
Unify the file so every order-determinable assertion follows the same convention. Prefer picking one convention for the whole file and swapping the operands of the assertions that use the other convention.
Quick fixes can rewrite every mismatched assertion in the file in either direction: put all expected values second (actual first), or put all actual values second (expected first).
import unittest
class TestRunner(unittest.TestCase):
def test_exit_code(self):
runner = Runner()
self.assertEqual(0, runner.exit_code) # Noncompliant; file mixes both orders
self.assertEqual(runner.name, "ok")
import unittest
class TestRunner(unittest.TestCase):
def test_exit_code(self):
runner = Runner()
self.assertEqual(runner.exit_code, 0)
self.assertEqual(runner.name, "ok")
import pytest
EXPECTED_PI = 3.14
def test_calculation():
result = perform_calculation()
assert 3.14 == result # Noncompliant; file mixes both orders
assert result == pytest.approx(EXPECTED_PI)
import pytest
EXPECTED_PI = 3.14
def test_calculation():
result = perform_calculation()
assert result == 3.14
assert result == pytest.approx(EXPECTED_PI)
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; file mixes both orders
assert_that(runner.name).is_equal_to("ok")
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)
assert_that(runner.name).is_equal_to("ok")