diff --git a/changelog/13503.bugfix.rst b/changelog/13503.bugfix.rst new file mode 100644 index 00000000000..3c262652c38 --- /dev/null +++ b/changelog/13503.bugfix.rst @@ -0,0 +1,2 @@ +Preserved insertion order for extra dictionary items in assertion failure output. +Display dictionary differences in assertion failures using the original key insertion order instead of sorted order. diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index f35d83a6fe4..a5bcc5d02ad 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -520,7 +520,7 @@ def _compare_eq_dict( + " != " + highlighter(saferepr({k: right[k]})) ] - extra_left = set_left - set_right + extra_left = [k for k in left if k not in right] len_extra_left = len(extra_left) if len_extra_left: explanation.append( @@ -529,7 +529,7 @@ def _compare_eq_dict( explanation.extend( highlighter(pprint.pformat({k: left[k] for k in extra_left})).splitlines() ) - extra_right = set_right - set_left + extra_right = [k for k in right if k not in left] len_extra_right = len(extra_right) if len_extra_right: explanation.append( diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 5179b13b0e9..94bb6827ff6 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -2,6 +2,7 @@ from __future__ import annotations from collections.abc import MutableSequence +import re import sys import textwrap from typing import Any @@ -2198,3 +2199,35 @@ def test_vvv(): ] ) result.stdout.no_fnmatch_line(expected_non_vvv_arg_line) + + +def test_dict_extra_items_preserve_insertion_order(pytester): + pytester.makepyfile( + test_order=""" + def test_order(): + a = { + "first": 1, + "second": 2, + } + assert a == {} + """ + ) + + result = pytester.runpytest() + + stdout = result.stdout.str() + stdout = re.sub(r"\x1b\[[0-9;]*m", "", stdout) + + assert "Left contains 2 more items:" in stdout + + dict_line = next( + line + for line in stdout.splitlines() + if "{" in line and "}" in line and "first" in line + ) + + first = dict_line.find("first") + second = dict_line.find("second") + + assert first != -1 and second != -1 + assert first < second