diff --git a/doc/source/whatsnew/v1.6.0.rst b/doc/source/whatsnew/v1.6.0.rst index ee5085fd9ad89..5c4de03cb8a10 100644 --- a/doc/source/whatsnew/v1.6.0.rst +++ b/doc/source/whatsnew/v1.6.0.rst @@ -29,6 +29,7 @@ enhancement2 Other enhancements ^^^^^^^^^^^^^^^^^^ - :meth:`Series.add_suffix`, :meth:`DataFrame.add_suffix`, :meth:`Series.add_prefix` and :meth:`DataFrame.add_prefix` support an ``axis`` argument. If ``axis`` is set, the default behaviour of which axis to consider can be overwritten (:issue:`47819`) +- :func:`assert_frame_equal` now shows the first element where the DataFrames differ, analogously to ``pytest``'s output (:issue:`47910`) - .. --------------------------------------------------------------------------- diff --git a/pandas/_libs/testing.pyx b/pandas/_libs/testing.pyx index cfe9f40f12452..e710a6fb6b24e 100644 --- a/pandas/_libs/testing.pyx +++ b/pandas/_libs/testing.pyx @@ -91,6 +91,7 @@ cpdef assert_almost_equal(a, b, Py_ssize_t i, na, nb double fa, fb bint is_unequal = False, a_is_ndarray, b_is_ndarray + str first_diff = '' if lobj is None: lobj = a @@ -159,12 +160,14 @@ cpdef assert_almost_equal(a, b, except AssertionError: is_unequal = True diff += 1 + if not first_diff: + first_diff = f"At positional index {i}, first diff: {a[i]} != {b[i]}" if is_unequal: from pandas._testing import raise_assert_detail msg = (f"{obj} values are different " f"({np.round(diff * 100.0 / na, 5)} %)") - raise_assert_detail(obj, msg, lobj, robj, index_values=index_values) + raise_assert_detail(obj, msg, lobj, robj, first_diff=first_diff, index_values=index_values) return True diff --git a/pandas/_testing/asserters.py b/pandas/_testing/asserters.py index 945639ef4b00a..3858670850074 100644 --- a/pandas/_testing/asserters.py +++ b/pandas/_testing/asserters.py @@ -639,7 +639,9 @@ def assert_timedelta_array_equal( assert_attr_equal("freq", left, right, obj=obj) -def raise_assert_detail(obj, message, left, right, diff=None, index_values=None): +def raise_assert_detail( + obj, message, left, right, diff=None, first_diff=None, index_values=None +): __tracebackhide__ = True msg = f"""{obj} are different @@ -674,6 +676,9 @@ def raise_assert_detail(obj, message, left, right, diff=None, index_values=None) if diff is not None: msg += f"\n[diff]: {diff}" + if first_diff is not None: + msg += f"\n{first_diff}" + raise AssertionError(msg) diff --git a/pandas/tests/util/test_assert_frame_equal.py b/pandas/tests/util/test_assert_frame_equal.py index 6ff1a1c17b179..8139ffed78f7f 100644 --- a/pandas/tests/util/test_assert_frame_equal.py +++ b/pandas/tests/util/test_assert_frame_equal.py @@ -151,7 +151,8 @@ def test_frame_equal_index_mismatch(check_like, obj_fixture): {obj_fixture}\\.index values are different \\(33\\.33333 %\\) \\[left\\]: Index\\(\\['a', 'b', 'c'\\], dtype='object'\\) -\\[right\\]: Index\\(\\['a', 'b', 'd'\\], dtype='object'\\)""" +\\[right\\]: Index\\(\\['a', 'b', 'd'\\], dtype='object'\\) +At positional index 2, first diff: c != d""" df1 = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, index=["a", "b", "c"]) df2 = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, index=["a", "b", "d"])