diff --git a/changelog/13503.bugfix.rst b/changelog/13503.bugfix.rst new file mode 100644 index 00000000000..473a8b46e38 --- /dev/null +++ b/changelog/13503.bugfix.rst @@ -0,0 +1 @@ +Fixes dict output in assertion failures to preserve insertion order. (#13503) diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index cee70e332f9..fab22f445cc 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -87,7 +87,7 @@ def safeformat(obj: object) -> str: with a short exception info. """ try: - return pprint.pformat(obj) + return pprint.pformat(obj, sort_dicts=False) except Exception as exc: return _format_repr_exception(exc, obj) diff --git a/testing/io/test_saferepr.py b/testing/io/test_saferepr.py index 075d40cdf44..ec7f4480b1d 100644 --- a/testing/io/test_saferepr.py +++ b/testing/io/test_saferepr.py @@ -192,3 +192,15 @@ def __repr__(self): assert saferepr_unlimited(A()).startswith( "<[ValueError(42) raised in repr()] A object at 0x" ) + + +def test_saferepr_dict_insertion_order(): + from _pytest._io.saferepr import safeformat + + d = {} + d["z"] = 1 + d["a"] = 2 + d["m"] = 3 + output = safeformat(d) + # output should contain 'z', 'a', 'm' in this order (not 'a', 'm', 'z') + assert output.find("'z'") < output.find("'a'") < output.find("'m'")