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.

Why is this an issue?

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):

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.

What is the potential impact?

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.

How to fix it

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).

Code examples

Noncompliant code example

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")

Compliant solution

import unittest

class TestRunner(unittest.TestCase):
    def test_exit_code(self):
        runner = Runner()
        self.assertEqual(runner.exit_code, 0)
        self.assertEqual(runner.name, "ok")

Noncompliant code example

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)

Compliant solution

import pytest

EXPECTED_PI = 3.14

def test_calculation():
    result = perform_calculation()
    assert result == 3.14
    assert result == pytest.approx(EXPECTED_PI)

Noncompliant code example

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")

Compliant solution

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")

Resources

Documentation