diff --git a/pandas/_libs/testing.pyx b/pandas/_libs/testing.pyx index 0e57b563d4d25..c6b8c3e876390 100644 --- a/pandas/_libs/testing.pyx +++ b/pandas/_libs/testing.pyx @@ -65,7 +65,7 @@ cpdef assert_dict_equal(a, b, bint compare_keys=True): cpdef assert_almost_equal(a, b, check_less_precise=False, bint check_dtype=True, - obj=None, lobj=None, robj=None): + obj=None, lobj=None, robj=None, index_values=None): """ Check that left and right objects are almost equal. @@ -89,6 +89,12 @@ cpdef assert_almost_equal(a, b, robj : str, default None Specify right object name being compared, internally used to show appropriate assertion message + index_values : ndarray, default None + Specify shared index values of objects being compared, internally used + to show appropriate assertion message + + .. versionadded:: 1.1.0 + """ cdef: int decimal @@ -171,7 +177,7 @@ cpdef assert_almost_equal(a, b, 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) + raise_assert_detail(obj, msg, lobj, robj, index_values=index_values) return True diff --git a/pandas/_testing.py b/pandas/_testing.py index dff15c66750ac..db5d141cc0051 100644 --- a/pandas/_testing.py +++ b/pandas/_testing.py @@ -888,9 +888,16 @@ def assert_timedelta_array_equal(left, right, obj="TimedeltaArray"): assert_attr_equal("freq", left, right, obj=obj) -def raise_assert_detail(obj, message, left, right, diff=None): +def raise_assert_detail(obj, message, left, right, diff=None, index_values=None): __tracebackhide__ = True + msg = f"""{obj} are different + +{message}""" + + if isinstance(index_values, np.ndarray): + msg += f"\n[index]: {pprint_thing(index_values)}" + if isinstance(left, np.ndarray): left = pprint_thing(left) elif is_categorical_dtype(left): @@ -901,9 +908,7 @@ def raise_assert_detail(obj, message, left, right, diff=None): elif is_categorical_dtype(right): right = repr(right) - msg = f"""{obj} are different - -{message} + msg += f""" [left]: {left} [right]: {right}""" @@ -921,6 +926,7 @@ def assert_numpy_array_equal( err_msg=None, check_same=None, obj="numpy array", + index_values=None, ): """ Check that 'np.ndarray' is equivalent. @@ -940,6 +946,8 @@ def assert_numpy_array_equal( obj : str, default 'numpy array' Specify object name being compared, internally used to show appropriate assertion message. + index_values : numpy.ndarray, default None + optional index (shared by both left and right), used in output. """ __tracebackhide__ = True @@ -977,7 +985,7 @@ def _raise(left, right, err_msg): diff = diff * 100.0 / left.size msg = f"{obj} values are different ({np.round(diff, 5)} %)" - raise_assert_detail(obj, msg, left, right) + raise_assert_detail(obj, msg, left, right, index_values=index_values) raise AssertionError(err_msg) @@ -1142,7 +1150,11 @@ def assert_series_equal( raise AssertionError("check_exact may only be used with numeric Series") assert_numpy_array_equal( - left._values, right._values, check_dtype=check_dtype, obj=str(obj) + left._values, + right._values, + check_dtype=check_dtype, + obj=str(obj), + index_values=np.asarray(left.index), ) elif check_datetimelike_compat and ( needs_i8_conversion(left.dtype) or needs_i8_conversion(right.dtype) @@ -1181,6 +1193,7 @@ def assert_series_equal( check_less_precise=check_less_precise, check_dtype=check_dtype, obj=str(obj), + index_values=np.asarray(left.index), ) # metadata comparison diff --git a/pandas/tests/util/test_assert_frame_equal.py b/pandas/tests/util/test_assert_frame_equal.py index 3090343ba2fd9..b6b0ca53d1fdb 100644 --- a/pandas/tests/util/test_assert_frame_equal.py +++ b/pandas/tests/util/test_assert_frame_equal.py @@ -177,6 +177,7 @@ def test_frame_equal_block_mismatch(by_blocks_fixture, obj_fixture): msg = f"""{obj}\\.iloc\\[:, 1\\] \\(column name="B"\\) are different {obj}\\.iloc\\[:, 1\\] \\(column name="B"\\) values are different \\(33\\.33333 %\\) +\\[index\\]: \\[0, 1, 2\\] \\[left\\]: \\[4, 5, 6\\] \\[right\\]: \\[4, 5, 7\\]""" @@ -196,6 +197,7 @@ def test_frame_equal_block_mismatch(by_blocks_fixture, obj_fixture): """{obj}\\.iloc\\[:, 1\\] \\(column name="E"\\) are different {obj}\\.iloc\\[:, 1\\] \\(column name="E"\\) values are different \\(33\\.33333 %\\) +\\[index\\]: \\[0, 1, 2\\] \\[left\\]: \\[é, è, ë\\] \\[right\\]: \\[é, è, e̊\\]""", ), @@ -205,6 +207,7 @@ def test_frame_equal_block_mismatch(by_blocks_fixture, obj_fixture): """{obj}\\.iloc\\[:, 0\\] \\(column name="A"\\) are different {obj}\\.iloc\\[:, 0\\] \\(column name="A"\\) values are different \\(100\\.0 %\\) +\\[index\\]: \\[0, 1, 2\\] \\[left\\]: \\[á, à, ä\\] \\[right\\]: \\[a, a, a\\]""", ), diff --git a/pandas/tests/util/test_assert_series_equal.py b/pandas/tests/util/test_assert_series_equal.py index eaf0824f52927..a77c57fb5411c 100644 --- a/pandas/tests/util/test_assert_series_equal.py +++ b/pandas/tests/util/test_assert_series_equal.py @@ -168,6 +168,7 @@ def test_series_equal_values_mismatch(check_less_precise): msg = """Series are different Series values are different \\(33\\.33333 %\\) +\\[index\\]: \\[0, 1, 2\\] \\[left\\]: \\[1, 2, 3\\] \\[right\\]: \\[1, 2, 4\\]"""