From aca6404428592a210f972b1e9cf3b50a711cb1ee Mon Sep 17 00:00:00 2001 From: gfyoung Date: Wed, 19 Dec 2018 22:20:21 -0800 Subject: [PATCH] REF/TST: Add pytest idiom to test_testing Splits test file into multiple new files and delegates remaining tests to the miscellaneous test_util.py --- ci/code_checks.sh | 2 +- pandas/tests/util/conftest.py | 26 + pandas/tests/util/test_assert_almost_equal.py | 350 +++++++ .../util/test_assert_categorical_equal.py | 92 ++ .../util/test_assert_extension_array_equal.py | 102 ++ pandas/tests/util/test_assert_frame_equal.py | 209 ++++ pandas/tests/util/test_assert_index_equal.py | 179 ++++ .../util/test_assert_interval_array_equal.py | 80 ++ .../util/test_assert_numpy_array_equal.py | 177 ++++ pandas/tests/util/test_assert_series_equal.py | 185 ++++ pandas/tests/util/test_testing.py | 984 ------------------ pandas/tests/util/test_util.py | 88 +- 12 files changed, 1484 insertions(+), 990 deletions(-) create mode 100644 pandas/tests/util/conftest.py create mode 100644 pandas/tests/util/test_assert_almost_equal.py create mode 100644 pandas/tests/util/test_assert_categorical_equal.py create mode 100644 pandas/tests/util/test_assert_extension_array_equal.py create mode 100644 pandas/tests/util/test_assert_frame_equal.py create mode 100644 pandas/tests/util/test_assert_index_equal.py create mode 100644 pandas/tests/util/test_assert_interval_array_equal.py create mode 100644 pandas/tests/util/test_assert_numpy_array_equal.py create mode 100644 pandas/tests/util/test_assert_series_equal.py delete mode 100644 pandas/tests/util/test_testing.py diff --git a/ci/code_checks.sh b/ci/code_checks.sh index 0c9a24801f98c..b594f6a2f8df6 100755 --- a/ci/code_checks.sh +++ b/ci/code_checks.sh @@ -145,7 +145,7 @@ if [[ -z "$CHECK" || "$CHECK" == "patterns" ]]; then RET=$(($RET + $?)) ; echo $MSG "DONE" MSG='Check that the deprecated `assert_raises_regex` is not used (`pytest.raises(match=pattern)` should be used instead)' ; echo $MSG - invgrep -R --exclude=*.pyc --exclude=testing.py --exclude=test_testing.py assert_raises_regex pandas + invgrep -R --exclude=*.pyc --exclude=testing.py --exclude=test_util.py assert_raises_regex pandas RET=$(($RET + $?)) ; echo $MSG "DONE" # Check that we use pytest.raises only as a context manager diff --git a/pandas/tests/util/conftest.py b/pandas/tests/util/conftest.py new file mode 100644 index 0000000000000..5eff49ab774b5 --- /dev/null +++ b/pandas/tests/util/conftest.py @@ -0,0 +1,26 @@ +import pytest + + +@pytest.fixture(params=[True, False]) +def check_dtype(request): + return request.param + + +@pytest.fixture(params=[True, False]) +def check_exact(request): + return request.param + + +@pytest.fixture(params=[True, False]) +def check_index_type(request): + return request.param + + +@pytest.fixture(params=[True, False]) +def check_less_precise(request): + return request.param + + +@pytest.fixture(params=[True, False]) +def check_categorical(request): + return request.param diff --git a/pandas/tests/util/test_assert_almost_equal.py b/pandas/tests/util/test_assert_almost_equal.py new file mode 100644 index 0000000000000..afee9c008295f --- /dev/null +++ b/pandas/tests/util/test_assert_almost_equal.py @@ -0,0 +1,350 @@ +# -*- coding: utf-8 -*- + +import numpy as np +import pytest + +from pandas import DataFrame, Index, Series, Timestamp +from pandas.util.testing import assert_almost_equal + + +def _assert_almost_equal_both(a, b, **kwargs): + """ + Check that two objects are approximately equal. + + This check is performed commutatively. + + Parameters + ---------- + a : object + The first object to compare. + b : object + The second object to compare. + kwargs : dict + The arguments passed to `assert_almost_equal`. + """ + assert_almost_equal(a, b, **kwargs) + assert_almost_equal(b, a, **kwargs) + + +def _assert_not_almost_equal(a, b, **kwargs): + """ + Check that two objects are not approximately equal. + + Parameters + ---------- + a : object + The first object to compare. + b : object + The second object to compare. + kwargs : dict + The arguments passed to `assert_almost_equal`. + """ + try: + assert_almost_equal(a, b, **kwargs) + msg = ("{a} and {b} were approximately equal " + "when they shouldn't have been").format(a=a, b=b) + pytest.fail(msg=msg) + except AssertionError: + pass + + +def _assert_not_almost_equal_both(a, b, **kwargs): + """ + Check that two objects are not approximately equal. + + This check is performed commutatively. + + Parameters + ---------- + a : object + The first object to compare. + b : object + The second object to compare. + kwargs : dict + The arguments passed to `tm.assert_almost_equal`. + """ + _assert_not_almost_equal(a, b, **kwargs) + _assert_not_almost_equal(b, a, **kwargs) + + +@pytest.mark.parametrize("a,b", [ + (1.1, 1.1), (1.1, 1.100001), (np.int16(1), 1.000001), + (np.float64(1.1), 1.1), (np.uint32(5), 5), +]) +def test_assert_almost_equal_numbers(a, b): + _assert_almost_equal_both(a, b) + + +@pytest.mark.parametrize("a,b", [ + (1.1, 1), (1.1, True), (1, 2), (1.0001, np.int16(1)), +]) +def test_assert_not_almost_equal_numbers(a, b): + _assert_not_almost_equal_both(a, b) + + +@pytest.mark.parametrize("a,b", [ + (0, 0), (0, 0.0), (0, np.float64(0)), (0.000001, 0), +]) +def test_assert_almost_equal_numbers_with_zeros(a, b): + _assert_almost_equal_both(a, b) + + +@pytest.mark.parametrize("a,b", [ + (0.001, 0), (1, 0), +]) +def test_assert_not_almost_equal_numbers_with_zeros(a, b): + _assert_not_almost_equal_both(a, b) + + +@pytest.mark.parametrize("a,b", [ + (1, "abc"), (1, [1, ]), (1, object()), +]) +def test_assert_not_almost_equal_numbers_with_mixed(a, b): + _assert_not_almost_equal_both(a, b) + + +@pytest.mark.parametrize( + "left_dtype", ["M8[ns]", "m8[ns]", "float64", "int64", "object"]) +@pytest.mark.parametrize( + "right_dtype", ["M8[ns]", "m8[ns]", "float64", "int64", "object"]) +def test_assert_almost_equal_edge_case_ndarrays(left_dtype, right_dtype): + # Empty compare. + _assert_almost_equal_both(np.array([], dtype=left_dtype), + np.array([], dtype=right_dtype), + check_dtype=False) + + +def test_assert_almost_equal_dicts(): + _assert_almost_equal_both({"a": 1, "b": 2}, {"a": 1, "b": 2}) + + +@pytest.mark.parametrize("a,b", [ + ({"a": 1, "b": 2}, {"a": 1, "b": 3}), + ({"a": 1, "b": 2}, {"a": 1, "b": 2, "c": 3}), + ({"a": 1}, 1), ({"a": 1}, "abc"), ({"a": 1}, [1, ]), +]) +def test_assert_not_almost_equal_dicts(a, b): + _assert_not_almost_equal_both(a, b) + + +@pytest.mark.parametrize("val", [1, 2]) +def test_assert_almost_equal_dict_like_object(val): + dict_val = 1 + real_dict = dict(a=val) + + class DictLikeObj(object): + def keys(self): + return "a", + + def __getitem__(self, item): + if item == "a": + return dict_val + + func = (_assert_almost_equal_both if val == dict_val + else _assert_not_almost_equal_both) + func(real_dict, DictLikeObj(), check_dtype=False) + + +def test_assert_almost_equal_strings(): + _assert_almost_equal_both("abc", "abc") + + +@pytest.mark.parametrize("a,b", [ + ("abc", "abcd"), ("abc", "abd"), ("abc", 1), ("abc", [1, ]), +]) +def test_assert_not_almost_equal_strings(a, b): + _assert_not_almost_equal_both(a, b) + + +@pytest.mark.parametrize("a,b", [ + ([1, 2, 3], [1, 2, 3]), (np.array([1, 2, 3]), np.array([1, 2, 3])), +]) +def test_assert_almost_equal_iterables(a, b): + _assert_almost_equal_both(a, b) + + +@pytest.mark.parametrize("a,b", [ + # Class is different. + (np.array([1, 2, 3]), [1, 2, 3]), + + # Dtype is different. + (np.array([1, 2, 3]), np.array([1., 2., 3.])), + + # Can't compare generators. + (iter([1, 2, 3]), [1, 2, 3]), ([1, 2, 3], [1, 2, 4]), + ([1, 2, 3], [1, 2, 3, 4]), ([1, 2, 3], 1), +]) +def test_assert_not_almost_equal_iterables(a, b): + _assert_not_almost_equal(a, b) + + +def test_assert_almost_equal_null(): + _assert_almost_equal_both(None, None) + + +@pytest.mark.parametrize("a,b", [ + (None, np.NaN), (None, 0), (np.NaN, 0), +]) +def test_assert_not_almost_equal_null(a, b): + _assert_not_almost_equal(a, b) + + +@pytest.mark.parametrize("a,b", [ + (np.inf, np.inf), (np.inf, float("inf")), + (np.array([np.inf, np.nan, -np.inf]), + np.array([np.inf, np.nan, -np.inf])), + (np.array([np.inf, None, -np.inf], dtype=np.object_), + np.array([np.inf, np.nan, -np.inf], dtype=np.object_)), +]) +def test_assert_almost_equal_inf(a, b): + _assert_almost_equal_both(a, b) + + +def test_assert_not_almost_equal_inf(): + _assert_not_almost_equal_both(np.inf, 0) + + +@pytest.mark.parametrize("a,b", [ + (Index([1., 1.1]), Index([1., 1.100001])), + (Series([1., 1.1]), Series([1., 1.100001])), + (np.array([1.1, 2.000001]), np.array([1.1, 2.0])), + (DataFrame({"a": [1., 1.1]}), DataFrame({"a": [1., 1.100001]})) +]) +def test_assert_almost_equal_pandas(a, b): + _assert_almost_equal_both(a, b) + + +def test_assert_almost_equal_object(): + a = [Timestamp("2011-01-01"), Timestamp("2011-01-01")] + b = [Timestamp("2011-01-01"), Timestamp("2011-01-01")] + _assert_almost_equal_both(a, b) + + +def test_assert_almost_equal_value_mismatch(): + msg = "expected 2\\.00000 but got 1\\.00000, with decimal 5" + + with pytest.raises(AssertionError, match=msg): + assert_almost_equal(1, 2) + + +@pytest.mark.parametrize("a,b,klass1,klass2", [ + (np.array([1]), 1, "ndarray", "int"), + (1, np.array([1]), "int", "ndarray"), +]) +def test_assert_almost_equal_class_mismatch(a, b, klass1, klass2): + msg = """numpy array are different + +numpy array classes are different +\\[left\\]: {klass1} +\\[right\\]: {klass2}""".format(klass1=klass1, klass2=klass2) + + with pytest.raises(AssertionError, match=msg): + assert_almost_equal(a, b) + + +def test_assert_almost_equal_value_mismatch1(): + msg = """numpy array are different + +numpy array values are different \\(66\\.66667 %\\) +\\[left\\]: \\[nan, 2\\.0, 3\\.0\\] +\\[right\\]: \\[1\\.0, nan, 3\\.0\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_almost_equal(np.array([np.nan, 2, 3]), + np.array([1, np.nan, 3])) + + +def test_assert_almost_equal_value_mismatch2(): + msg = """numpy array are different + +numpy array values are different \\(50\\.0 %\\) +\\[left\\]: \\[1, 2\\] +\\[right\\]: \\[1, 3\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_almost_equal(np.array([1, 2]), np.array([1, 3])) + + +def test_assert_almost_equal_value_mismatch3(): + msg = """numpy array are different + +numpy array values are different \\(16\\.66667 %\\) +\\[left\\]: \\[\\[1, 2\\], \\[3, 4\\], \\[5, 6\\]\\] +\\[right\\]: \\[\\[1, 3\\], \\[3, 4\\], \\[5, 6\\]\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_almost_equal(np.array([[1, 2], [3, 4], [5, 6]]), + np.array([[1, 3], [3, 4], [5, 6]])) + + +def test_assert_almost_equal_value_mismatch4(): + msg = """numpy array are different + +numpy array values are different \\(25\\.0 %\\) +\\[left\\]: \\[\\[1, 2\\], \\[3, 4\\]\\] +\\[right\\]: \\[\\[1, 3\\], \\[3, 4\\]\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_almost_equal(np.array([[1, 2], [3, 4]]), + np.array([[1, 3], [3, 4]])) + + +def test_assert_almost_equal_shape_mismatch_override(): + msg = """Index are different + +Index shapes are different +\\[left\\]: \\(2L*,\\) +\\[right\\]: \\(3L*,\\)""" + with pytest.raises(AssertionError, match=msg): + assert_almost_equal(np.array([1, 2]), + np.array([3, 4, 5]), + obj="Index") + + +def test_assert_almost_equal_unicode(): + # see gh-20503 + msg = """numpy array are different + +numpy array values are different \\(33\\.33333 %\\) +\\[left\\]: \\[á, à, ä\\] +\\[right\\]: \\[á, à, å\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_almost_equal(np.array([u"á", u"à", u"ä"]), + np.array([u"á", u"à", u"å"])) + + +def test_assert_almost_equal_timestamp(): + a = np.array([Timestamp("2011-01-01"), Timestamp("2011-01-01")]) + b = np.array([Timestamp("2011-01-01"), Timestamp("2011-01-02")]) + + msg = """numpy array are different + +numpy array values are different \\(50\\.0 %\\) +\\[left\\]: \\[2011-01-01 00:00:00, 2011-01-01 00:00:00\\] +\\[right\\]: \\[2011-01-01 00:00:00, 2011-01-02 00:00:00\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_almost_equal(a, b) + + +def test_assert_almost_equal_iterable_length_mismatch(): + msg = """Iterable are different + +Iterable length are different +\\[left\\]: 2 +\\[right\\]: 3""" + + with pytest.raises(AssertionError, match=msg): + assert_almost_equal([1, 2], [3, 4, 5]) + + +def test_assert_almost_equal_iterable_values_mismatch(): + msg = """Iterable are different + +Iterable values are different \\(50\\.0 %\\) +\\[left\\]: \\[1, 2\\] +\\[right\\]: \\[1, 3\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_almost_equal([1, 2], [1, 3]) diff --git a/pandas/tests/util/test_assert_categorical_equal.py b/pandas/tests/util/test_assert_categorical_equal.py new file mode 100644 index 0000000000000..04c8301027039 --- /dev/null +++ b/pandas/tests/util/test_assert_categorical_equal.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- + +import pytest + +from pandas import Categorical +from pandas.util.testing import assert_categorical_equal + + +@pytest.mark.parametrize("c", [ + Categorical([1, 2, 3, 4]), + Categorical([1, 2, 3, 4], categories=[1, 2, 3, 4, 5]), +]) +def test_categorical_equal(c): + assert_categorical_equal(c, c) + + +@pytest.mark.parametrize("check_category_order", [True, False]) +def test_categorical_equal_order_mismatch(check_category_order): + c1 = Categorical([1, 2, 3, 4], categories=[1, 2, 3, 4]) + c2 = Categorical([1, 2, 3, 4], categories=[4, 3, 2, 1]) + kwargs = dict(check_category_order=check_category_order) + + if check_category_order: + msg = """Categorical\\.categories are different + +Categorical\\.categories values are different \\(100\\.0 %\\) +\\[left\\]: Int64Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\) +\\[right\\]: Int64Index\\(\\[4, 3, 2, 1\\], dtype='int64'\\)""" + with pytest.raises(AssertionError, match=msg): + assert_categorical_equal(c1, c2, **kwargs) + else: + assert_categorical_equal(c1, c2, **kwargs) + + +def test_categorical_equal_categories_mismatch(): + msg = """Categorical\\.categories are different + +Categorical\\.categories values are different \\(25\\.0 %\\) +\\[left\\]: Int64Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\) +\\[right\\]: Int64Index\\(\\[1, 2, 3, 5\\], dtype='int64'\\)""" + + c1 = Categorical([1, 2, 3, 4]) + c2 = Categorical([1, 2, 3, 5]) + + with pytest.raises(AssertionError, match=msg): + assert_categorical_equal(c1, c2) + + +def test_categorical_equal_codes_mismatch(): + categories = [1, 2, 3, 4] + msg = """Categorical\\.codes are different + +Categorical\\.codes values are different \\(50\\.0 %\\) +\\[left\\]: \\[0, 1, 3, 2\\] +\\[right\\]: \\[0, 1, 2, 3\\]""" + + c1 = Categorical([1, 2, 4, 3], categories=categories) + c2 = Categorical([1, 2, 3, 4], categories=categories) + + with pytest.raises(AssertionError, match=msg): + assert_categorical_equal(c1, c2) + + +def test_categorical_equal_ordered_mismatch(): + data = [1, 2, 3, 4] + msg = """Categorical are different + +Attribute "ordered" are different +\\[left\\]: False +\\[right\\]: True""" + + c1 = Categorical(data, ordered=False) + c2 = Categorical(data, ordered=True) + + with pytest.raises(AssertionError, match=msg): + assert_categorical_equal(c1, c2) + + +@pytest.mark.parametrize("obj", ["index", "foo", "pandas"]) +def test_categorical_equal_object_override(obj): + data = [1, 2, 3, 4] + msg = """{obj} are different + +Attribute "ordered" are different +\\[left\\]: False +\\[right\\]: True""".format(obj=obj) + + c1 = Categorical(data, ordered=False) + c2 = Categorical(data, ordered=True) + + with pytest.raises(AssertionError, match=msg): + assert_categorical_equal(c1, c2, obj=obj) diff --git a/pandas/tests/util/test_assert_extension_array_equal.py b/pandas/tests/util/test_assert_extension_array_equal.py new file mode 100644 index 0000000000000..3149078a56783 --- /dev/null +++ b/pandas/tests/util/test_assert_extension_array_equal.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- + +import numpy as np +import pytest + +from pandas.core.arrays.sparse import SparseArray +from pandas.util.testing import assert_extension_array_equal + + +@pytest.mark.parametrize("kwargs", [ + dict(), # Default is check_exact=False + dict(check_exact=False), dict(check_exact=True) +]) +def test_assert_extension_array_equal_not_exact(kwargs): + # see gh-23709 + arr1 = SparseArray([-0.17387645482451206, 0.3414148016424936]) + arr2 = SparseArray([-0.17387645482451206, 0.3414148016424937]) + + if kwargs.get("check_exact", False): + msg = """\ +ExtensionArray are different + +ExtensionArray values are different \\(50\\.0 %\\) +\\[left\\]: \\[-0\\.17387645482.*, 0\\.341414801642.*\\] +\\[right\\]: \\[-0\\.17387645482.*, 0\\.341414801642.*\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_extension_array_equal(arr1, arr2, **kwargs) + else: + assert_extension_array_equal(arr1, arr2, **kwargs) + + +@pytest.mark.parametrize("check_less_precise", [ + True, False, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 +]) +def test_assert_extension_array_equal_less_precise(check_less_precise): + arr1 = SparseArray([0.5, 0.123456]) + arr2 = SparseArray([0.5, 0.123457]) + + kwargs = dict(check_less_precise=check_less_precise) + + if check_less_precise is False or check_less_precise >= 5: + msg = """\ +ExtensionArray are different + +ExtensionArray values are different \\(50\\.0 %\\) +\\[left\\]: \\[0\\.5, 0\\.123456\\] +\\[right\\]: \\[0\\.5, 0\\.123457\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_extension_array_equal(arr1, arr2, **kwargs) + else: + assert_extension_array_equal(arr1, arr2, **kwargs) + + +def test_assert_extension_array_equal_dtype_mismatch(check_dtype): + end = 5 + kwargs = dict(check_dtype=check_dtype) + + arr1 = SparseArray(np.arange(end, dtype="int64")) + arr2 = SparseArray(np.arange(end, dtype="int32")) + + if check_dtype: + msg = """\ +ExtensionArray are different + +Attribute "dtype" are different +\\[left\\]: Sparse\\[int64, 0\\] +\\[right\\]: Sparse\\[int32, 0\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_extension_array_equal(arr1, arr2, **kwargs) + else: + assert_extension_array_equal(arr1, arr2, **kwargs) + + +def test_assert_extension_array_equal_missing_values(): + arr1 = SparseArray([np.nan, 1, 2, np.nan]) + arr2 = SparseArray([np.nan, 1, 2, 3]) + + msg = """\ +ExtensionArray NA mask are different + +ExtensionArray NA mask values are different \\(25\\.0 %\\) +\\[left\\]: \\[True, False, False, True\\] +\\[right\\]: \\[True, False, False, False\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_extension_array_equal(arr1, arr2) + + +@pytest.mark.parametrize("side", ["left", "right"]) +def test_assert_extension_array_equal_non_extension_array(side): + numpy_array = np.arange(5) + extension_array = SparseArray(numpy_array) + + msg = "{side} is not an ExtensionArray".format(side=side) + args = ((numpy_array, extension_array) if side == "left" + else (extension_array, numpy_array)) + + with pytest.raises(AssertionError, match=msg): + assert_extension_array_equal(*args) diff --git a/pandas/tests/util/test_assert_frame_equal.py b/pandas/tests/util/test_assert_frame_equal.py new file mode 100644 index 0000000000000..1a941c0f0c265 --- /dev/null +++ b/pandas/tests/util/test_assert_frame_equal.py @@ -0,0 +1,209 @@ +# -*- coding: utf-8 -*- + +import pytest + +from pandas import DataFrame +from pandas.util.testing import assert_frame_equal + + +@pytest.fixture(params=[True, False]) +def by_blocks(request): + return request.param + + +def _assert_frame_equal_both(a, b, **kwargs): + """ + Check that two DataFrame equal. + + This check is performed commutatively. + + Parameters + ---------- + a : DataFrame + The first DataFrame to compare. + b : DataFrame + The second DataFrame to compare. + kwargs : dict + The arguments passed to `assert_frame_equal`. + """ + assert_frame_equal(a, b, **kwargs) + assert_frame_equal(b, a, **kwargs) + + +def _assert_not_frame_equal(a, b, **kwargs): + """ + Check that two DataFrame are not equal. + + Parameters + ---------- + a : DataFrame + The first DataFrame to compare. + b : DataFrame + The second DataFrame to compare. + kwargs : dict + The arguments passed to `assert_frame_equal`. + """ + try: + assert_frame_equal(a, b, **kwargs) + msg = "The two DataFrames were equal when they shouldn't have been" + + pytest.fail(msg=msg) + except AssertionError: + pass + + +def _assert_not_frame_equal_both(a, b, **kwargs): + """ + Check that two DataFrame are not equal. + + This check is performed commutatively. + + Parameters + ---------- + a : DataFrame + The first DataFrame to compare. + b : DataFrame + The second DataFrame to compare. + kwargs : dict + The arguments passed to `assert_frame_equal`. + """ + _assert_not_frame_equal(a, b, **kwargs) + _assert_not_frame_equal(b, a, **kwargs) + + +@pytest.mark.parametrize("check_like", [True, False]) +def test_frame_equal_row_order_mismatch(check_like): + df1 = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, + index=["a", "b", "c"]) + df2 = DataFrame({"A": [3, 2, 1], "B": [6, 5, 4]}, + index=["c", "b", "a"]) + + if not check_like: # Do not ignore row-column orderings. + msg = "DataFrame.index are different" + with pytest.raises(AssertionError, match=msg): + assert_frame_equal(df1, df2, check_like=check_like) + else: + _assert_frame_equal_both(df1, df2, check_like=check_like) + + +@pytest.mark.parametrize("df1,df2", [ + (DataFrame({"A": [1, 2, 3]}), DataFrame({"A": [1, 2, 3, 4]})), + (DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}), DataFrame({"A": [1, 2, 3]})), +]) +def test_frame_equal_shape_mismatch(df1, df2): + msg = "DataFrame are different" + + with pytest.raises(AssertionError, match=msg): + assert_frame_equal(df1, df2) + + +@pytest.mark.parametrize("df1,df2,msg", [ + # Index + (DataFrame.from_records({"a": [1, 2], + "c": ["l1", "l2"]}, index=["a"]), + DataFrame.from_records({"a": [1.0, 2.0], + "c": ["l1", "l2"]}, index=["a"]), + "DataFrame\\.index are different"), + + # MultiIndex + (DataFrame.from_records({"a": [1, 2], "b": [2.1, 1.5], + "c": ["l1", "l2"]}, index=["a", "b"]), + DataFrame.from_records({"a": [1.0, 2.0], "b": [2.1, 1.5], + "c": ["l1", "l2"]}, index=["a", "b"]), + "MultiIndex level \\[0\\] are different") +]) +def test_frame_equal_index_dtype_mismatch(df1, df2, msg, check_index_type): + kwargs = dict(check_index_type=check_index_type) + + if check_index_type: + with pytest.raises(AssertionError, match=msg): + assert_frame_equal(df1, df2, **kwargs) + else: + assert_frame_equal(df1, df2, **kwargs) + + +def test_empty_dtypes(check_dtype): + columns = ["col1", "col2"] + df1 = DataFrame(columns=columns) + df2 = DataFrame(columns=columns) + + kwargs = dict(check_dtype=check_dtype) + df1["col1"] = df1["col1"].astype("int64") + + if check_dtype: + msg = "Attributes are different" + with pytest.raises(AssertionError, match=msg): + assert_frame_equal(df1, df2, **kwargs) + else: + assert_frame_equal(df1, df2, **kwargs) + + +def test_frame_equal_index_mismatch(): + msg = """DataFrame\\.index are different + +DataFrame\\.index values are different \\(33\\.33333 %\\) +\\[left\\]: Index\\(\\[u?'a', u?'b', u?'c'\\], dtype='object'\\) +\\[right\\]: Index\\(\\[u?'a', u?'b', u?'d'\\], dtype='object'\\)""" + + 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"]) + + with pytest.raises(AssertionError, match=msg): + assert_frame_equal(df1, df2) + + +def test_frame_equal_columns_mismatch(): + msg = """DataFrame\\.columns are different + +DataFrame\\.columns values are different \\(50\\.0 %\\) +\\[left\\]: Index\\(\\[u?'A', u?'B'\\], dtype='object'\\) +\\[right\\]: Index\\(\\[u?'A', u?'b'\\], dtype='object'\\)""" + + 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", "c"]) + + with pytest.raises(AssertionError, match=msg): + assert_frame_equal(df1, df2) + + +def test_frame_equal_block_mismatch(by_blocks): + msg = """DataFrame\\.iloc\\[:, 1\\] are different + +DataFrame\\.iloc\\[:, 1\\] values are different \\(33\\.33333 %\\) +\\[left\\]: \\[4, 5, 6\\] +\\[right\\]: \\[4, 5, 7\\]""" + + df1 = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}) + df2 = DataFrame({"A": [1, 2, 3], "B": [4, 5, 7]}) + + with pytest.raises(AssertionError, match=msg): + assert_frame_equal(df1, df2, by_blocks=by_blocks) + + +@pytest.mark.parametrize("df1,df2,msg", [ + (DataFrame({"A": [u"á", u"à", u"ä"], "E": [u"é", u"è", u"ë"]}), + DataFrame({"A": [u"á", u"à", u"ä"], "E": [u"é", u"è", u"e̊"]}), + """DataFrame\\.iloc\\[:, 1\\] are different + +DataFrame\\.iloc\\[:, 1\\] values are different \\(33\\.33333 %\\) +\\[left\\]: \\[é, è, ë\\] +\\[right\\]: \\[é, è, e̊\\]"""), + (DataFrame({"A": [u"á", u"à", u"ä"], "E": [u"é", u"è", u"ë"]}), + DataFrame({"A": ["a", "a", "a"], "E": ["e", "e", "e"]}), + """DataFrame\\.iloc\\[:, 0\\] are different + +DataFrame\\.iloc\\[:, 0\\] values are different \\(100\\.0 %\\) +\\[left\\]: \\[á, à, ä\\] +\\[right\\]: \\[a, a, a\\]"""), +]) +def test_frame_equal_unicode(df1, df2, msg, by_blocks): + # see gh-20503 + # + # Test ensures that `assert_frame_equals` raises the right exception + # when comparing DataFrames containing differing unicode objects. + with pytest.raises(AssertionError, match=msg): + assert_frame_equal(df1, df2, by_blocks=by_blocks) diff --git a/pandas/tests/util/test_assert_index_equal.py b/pandas/tests/util/test_assert_index_equal.py new file mode 100644 index 0000000000000..b96345d4bd7ce --- /dev/null +++ b/pandas/tests/util/test_assert_index_equal.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- + +import numpy as np +import pytest + +from pandas import Categorical, Index, MultiIndex, NaT +from pandas.util.testing import assert_index_equal + + +def test_index_equal_levels_mismatch(): + msg = """Index are different + +Index levels are different +\\[left\\]: 1, Int64Index\\(\\[1, 2, 3\\], dtype='int64'\\) +\\[right\\]: 2, MultiIndex\\(levels=\\[\\[u?'A', u?'B'\\], \\[1, 2, 3, 4\\]\\], + labels=\\[\\[0, 0, 1, 1\\], \\[0, 1, 2, 3\\]\\]\\)""" + + idx1 = Index([1, 2, 3]) + idx2 = MultiIndex.from_tuples([("A", 1), ("A", 2), + ("B", 3), ("B", 4)]) + + with pytest.raises(AssertionError, match=msg): + assert_index_equal(idx1, idx2, exact=False) + + +def test_index_equal_values_mismatch(check_exact): + msg = """MultiIndex level \\[1\\] are different + +MultiIndex level \\[1\\] values are different \\(25\\.0 %\\) +\\[left\\]: Int64Index\\(\\[2, 2, 3, 4\\], dtype='int64'\\) +\\[right\\]: Int64Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)""" + + idx1 = MultiIndex.from_tuples([("A", 2), ("A", 2), + ("B", 3), ("B", 4)]) + idx2 = MultiIndex.from_tuples([("A", 1), ("A", 2), + ("B", 3), ("B", 4)]) + + with pytest.raises(AssertionError, match=msg): + assert_index_equal(idx1, idx2, check_exact=check_exact) + + +def test_index_equal_length_mismatch(check_exact): + msg = """Index are different + +Index length are different +\\[left\\]: 3, Int64Index\\(\\[1, 2, 3\\], dtype='int64'\\) +\\[right\\]: 4, Int64Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)""" + + idx1 = Index([1, 2, 3]) + idx2 = Index([1, 2, 3, 4]) + + with pytest.raises(AssertionError, match=msg): + assert_index_equal(idx1, idx2, check_exact=check_exact) + + +def test_index_equal_class_mismatch(check_exact): + msg = """Index are different + +Index classes are different +\\[left\\]: Int64Index\\(\\[1, 2, 3\\], dtype='int64'\\) +\\[right\\]: Float64Index\\(\\[1\\.0, 2\\.0, 3\\.0\\], dtype='float64'\\)""" + + idx1 = Index([1, 2, 3]) + idx2 = Index([1, 2, 3.0]) + + with pytest.raises(AssertionError, match=msg): + assert_index_equal(idx1, idx2, exact=True, check_exact=check_exact) + + +def test_index_equal_values_close(check_exact): + idx1 = Index([1, 2, 3.]) + idx2 = Index([1, 2, 3.0000000001]) + + if check_exact: + msg = """Index are different + +Index values are different \\(33\\.33333 %\\) +\\[left\\]: Float64Index\\(\\[1.0, 2.0, 3.0], dtype='float64'\\) +\\[right\\]: Float64Index\\(\\[1.0, 2.0, 3.0000000001\\], dtype='float64'\\)""" + + with pytest.raises(AssertionError, match=msg): + assert_index_equal(idx1, idx2, check_exact=check_exact) + else: + assert_index_equal(idx1, idx2, check_exact=check_exact) + + +def test_index_equal_values_less_close(check_exact, check_less_precise): + idx1 = Index([1, 2, 3.]) + idx2 = Index([1, 2, 3.0001]) + kwargs = dict(check_exact=check_exact, + check_less_precise=check_less_precise) + + if check_exact or not check_less_precise: + msg = """Index are different + +Index values are different \\(33\\.33333 %\\) +\\[left\\]: Float64Index\\(\\[1.0, 2.0, 3.0], dtype='float64'\\) +\\[right\\]: Float64Index\\(\\[1.0, 2.0, 3.0001\\], dtype='float64'\\)""" + + with pytest.raises(AssertionError, match=msg): + assert_index_equal(idx1, idx2, **kwargs) + else: + assert_index_equal(idx1, idx2, **kwargs) + + +def test_index_equal_values_too_far(check_exact, check_less_precise): + idx1 = Index([1, 2, 3]) + idx2 = Index([1, 2, 4]) + kwargs = dict(check_exact=check_exact, + check_less_precise=check_less_precise) + + msg = """Index are different + +Index values are different \\(33\\.33333 %\\) +\\[left\\]: Int64Index\\(\\[1, 2, 3\\], dtype='int64'\\) +\\[right\\]: Int64Index\\(\\[1, 2, 4\\], dtype='int64'\\)""" + + with pytest.raises(AssertionError, match=msg): + assert_index_equal(idx1, idx2, **kwargs) + + +def test_index_equal_level_values_mismatch(check_exact, check_less_precise): + idx1 = MultiIndex.from_tuples([("A", 2), ("A", 2), + ("B", 3), ("B", 4)]) + idx2 = MultiIndex.from_tuples([("A", 1), ("A", 2), + ("B", 3), ("B", 4)]) + kwargs = dict(check_exact=check_exact, + check_less_precise=check_less_precise) + + msg = """MultiIndex level \\[1\\] are different + +MultiIndex level \\[1\\] values are different \\(25\\.0 %\\) +\\[left\\]: Int64Index\\(\\[2, 2, 3, 4\\], dtype='int64'\\) +\\[right\\]: Int64Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)""" + + with pytest.raises(AssertionError, match=msg): + assert_index_equal(idx1, idx2, **kwargs) + + +@pytest.mark.parametrize("name1,name2", [ + (None, "x"), ("x", "x"), (np.nan, np.nan), (NaT, NaT), (np.nan, NaT) +]) +def test_index_equal_names(name1, name2): + msg = """Index are different + +Attribute "names" are different +\\[left\\]: \\[{name1}\\] +\\[right\\]: \\[{name2}\\]""" + + idx1 = Index([1, 2, 3], name=name1) + idx2 = Index([1, 2, 3], name=name2) + + if name1 == name2 or name1 is name2: + assert_index_equal(idx1, idx2) + else: + name1 = "u?'x'" if name1 == "x" else name1 + name2 = "u?'x'" if name2 == "x" else name2 + msg = msg.format(name1=name1, name2=name2) + + with pytest.raises(AssertionError, match=msg): + assert_index_equal(idx1, idx2) + + +def test_index_equal_category_mismatch(check_categorical): + msg = """Index are different + +Attribute "dtype" are different +\\[left\\]: CategoricalDtype\\(categories=\\[u?'a', u?'b'\\], ordered=False\\) +\\[right\\]: CategoricalDtype\\(categories=\\[u?'a', u?'b', u?'c'\\], \ +ordered=False\\)""" + + idx1 = Index(Categorical(["a", "b"])) + idx2 = Index(Categorical(["a", "b"], categories=["a", "b", "c"])) + + if check_categorical: + with pytest.raises(AssertionError, match=msg): + assert_index_equal(idx1, idx2, check_categorical=check_categorical) + else: + assert_index_equal(idx1, idx2, check_categorical=check_categorical) diff --git a/pandas/tests/util/test_assert_interval_array_equal.py b/pandas/tests/util/test_assert_interval_array_equal.py new file mode 100644 index 0000000000000..c81a27f9b3f19 --- /dev/null +++ b/pandas/tests/util/test_assert_interval_array_equal.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- + +import pytest + +from pandas import interval_range +from pandas.util.testing import assert_interval_array_equal + + +@pytest.mark.parametrize("kwargs", [ + dict(start=0, periods=4), + dict(start=1, periods=5), + dict(start=5, end=10, closed="left"), +]) +def test_interval_array_equal(kwargs): + arr = interval_range(**kwargs).values + assert_interval_array_equal(arr, arr) + + +def test_interval_array_equal_closed_mismatch(): + kwargs = dict(start=0, periods=5) + arr1 = interval_range(closed="left", **kwargs).values + arr2 = interval_range(closed="right", **kwargs).values + + msg = """\ +IntervalArray are different + +Attribute "closed" are different +\\[left\\]: left +\\[right\\]: right""" + + with pytest.raises(AssertionError, match=msg): + assert_interval_array_equal(arr1, arr2) + + +def test_interval_array_equal_periods_mismatch(): + kwargs = dict(start=0) + arr1 = interval_range(periods=5, **kwargs).values + arr2 = interval_range(periods=6, **kwargs).values + + msg = """\ +IntervalArray.left are different + +IntervalArray.left length are different +\\[left\\]: 5, Int64Index\\(\\[0, 1, 2, 3, 4\\], dtype='int64'\\) +\\[right\\]: 6, Int64Index\\(\\[0, 1, 2, 3, 4, 5\\], dtype='int64'\\)""" + + with pytest.raises(AssertionError, match=msg): + assert_interval_array_equal(arr1, arr2) + + +def test_interval_array_equal_end_mismatch(): + kwargs = dict(start=0, periods=5) + arr1 = interval_range(end=10, **kwargs).values + arr2 = interval_range(end=20, **kwargs).values + + msg = """\ +IntervalArray.left are different + +IntervalArray.left values are different \\(80.0 %\\) +\\[left\\]: Int64Index\\(\\[0, 2, 4, 6, 8\\], dtype='int64'\\) +\\[right\\]: Int64Index\\(\\[0, 4, 8, 12, 16\\], dtype='int64'\\)""" + + with pytest.raises(AssertionError, match=msg): + assert_interval_array_equal(arr1, arr2) + + +def test_interval_array_equal_start_mismatch(): + kwargs = dict(periods=4) + arr1 = interval_range(start=0, **kwargs).values + arr2 = interval_range(start=1, **kwargs).values + + msg = """\ +IntervalArray.left are different + +IntervalArray.left values are different \\(100.0 %\\) +\\[left\\]: Int64Index\\(\\[0, 1, 2, 3\\], dtype='int64'\\) +\\[right\\]: Int64Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)""" + + with pytest.raises(AssertionError, match=msg): + assert_interval_array_equal(arr1, arr2) diff --git a/pandas/tests/util/test_assert_numpy_array_equal.py b/pandas/tests/util/test_assert_numpy_array_equal.py new file mode 100644 index 0000000000000..99037fcf96194 --- /dev/null +++ b/pandas/tests/util/test_assert_numpy_array_equal.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- + +import numpy as np +import pytest + +from pandas import Timestamp +from pandas.util.testing import assert_numpy_array_equal + + +def test_assert_numpy_array_equal_shape_mismatch(): + msg = """numpy array are different + +numpy array shapes are different +\\[left\\]: \\(2L*,\\) +\\[right\\]: \\(3L*,\\)""" + + with pytest.raises(AssertionError, match=msg): + assert_numpy_array_equal(np.array([1, 2]), np.array([3, 4, 5])) + + +def test_assert_numpy_array_equal_bad_type(): + expected = "Expected type" + + with pytest.raises(AssertionError, match=expected): + assert_numpy_array_equal(1, 2) + + +@pytest.mark.parametrize("a,b,klass1,klass2", [ + (np.array([1]), 1, "ndarray", "int"), + (1, np.array([1]), "int", "ndarray"), +]) +def test_assert_numpy_array_equal_class_mismatch(a, b, klass1, klass2): + msg = """numpy array are different + +numpy array classes are different +\\[left\\]: {klass1} +\\[right\\]: {klass2}""".format(klass1=klass1, klass2=klass2) + + with pytest.raises(AssertionError, match=msg): + assert_numpy_array_equal(a, b) + + +def test_assert_numpy_array_equal_value_mismatch1(): + msg = """numpy array are different + +numpy array values are different \\(66\\.66667 %\\) +\\[left\\]: \\[nan, 2\\.0, 3\\.0\\] +\\[right\\]: \\[1\\.0, nan, 3\\.0\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_numpy_array_equal(np.array([np.nan, 2, 3]), + np.array([1, np.nan, 3])) + + +def test_assert_numpy_array_equal_value_mismatch2(): + msg = """numpy array are different + +numpy array values are different \\(50\\.0 %\\) +\\[left\\]: \\[1, 2\\] +\\[right\\]: \\[1, 3\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_numpy_array_equal(np.array([1, 2]), np.array([1, 3])) + + +def test_assert_numpy_array_equal_value_mismatch3(): + msg = """numpy array are different + +numpy array values are different \\(16\\.66667 %\\) +\\[left\\]: \\[\\[1, 2\\], \\[3, 4\\], \\[5, 6\\]\\] +\\[right\\]: \\[\\[1, 3\\], \\[3, 4\\], \\[5, 6\\]\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_numpy_array_equal(np.array([[1, 2], [3, 4], [5, 6]]), + np.array([[1, 3], [3, 4], [5, 6]])) + + +def test_assert_numpy_array_equal_value_mismatch4(): + msg = """numpy array are different + +numpy array values are different \\(50\\.0 %\\) +\\[left\\]: \\[1\\.1, 2\\.000001\\] +\\[right\\]: \\[1\\.1, 2.0\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_numpy_array_equal(np.array([1.1, 2.000001]), + np.array([1.1, 2.0])) + + +def test_assert_numpy_array_equal_value_mismatch5(): + msg = """numpy array are different + +numpy array values are different \\(16\\.66667 %\\) +\\[left\\]: \\[\\[1, 2\\], \\[3, 4\\], \\[5, 6\\]\\] +\\[right\\]: \\[\\[1, 3\\], \\[3, 4\\], \\[5, 6\\]\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_numpy_array_equal(np.array([[1, 2], [3, 4], [5, 6]]), + np.array([[1, 3], [3, 4], [5, 6]])) + + +def test_assert_numpy_array_equal_value_mismatch6(): + msg = """numpy array are different + +numpy array values are different \\(25\\.0 %\\) +\\[left\\]: \\[\\[1, 2\\], \\[3, 4\\]\\] +\\[right\\]: \\[\\[1, 3\\], \\[3, 4\\]\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_numpy_array_equal(np.array([[1, 2], [3, 4]]), + np.array([[1, 3], [3, 4]])) + + +def test_assert_numpy_array_equal_shape_mismatch_override(): + msg = """Index are different + +Index shapes are different +\\[left\\]: \\(2L*,\\) +\\[right\\]: \\(3L*,\\)""" + + with pytest.raises(AssertionError, match=msg): + assert_numpy_array_equal(np.array([1, 2]), + np.array([3, 4, 5]), + obj="Index") + + +def test_numpy_array_equal_unicode(): + # see gh-20503 + # + # Test ensures that `assert_numpy_array_equals` raises the right + # exception when comparing np.arrays containing differing unicode objects. + msg = """numpy array are different + +numpy array values are different \\(33\\.33333 %\\) +\\[left\\]: \\[á, à, ä\\] +\\[right\\]: \\[á, à, å\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_numpy_array_equal(np.array([u"á", u"à", u"ä"]), + np.array([u"á", u"à", u"å"])) + + +def test_numpy_array_equal_object(): + a = np.array([Timestamp("2011-01-01"), Timestamp("2011-01-01")]) + b = np.array([Timestamp("2011-01-01"), Timestamp("2011-01-02")]) + + msg = """numpy array are different + +numpy array values are different \\(50\\.0 %\\) +\\[left\\]: \\[2011-01-01 00:00:00, 2011-01-01 00:00:00\\] +\\[right\\]: \\[2011-01-01 00:00:00, 2011-01-02 00:00:00\\]""" + + with pytest.raises(AssertionError, match=msg): + assert_numpy_array_equal(a, b) + + +@pytest.mark.parametrize("other_type", ["same", "copy"]) +@pytest.mark.parametrize("check_same", ["same", "copy"]) +def test_numpy_array_equal_copy_flag(other_type, check_same): + a = np.array([1, 2, 3]) + msg = None + + if other_type == "same": + other = a.view() + else: + other = a.copy() + + if check_same != other_type: + msg = (r"array\(\[1, 2, 3\]\) is not array\(\[1, 2, 3\]\)" + if check_same == "same" + else r"array\(\[1, 2, 3\]\) is array\(\[1, 2, 3\]\)") + + if msg is not None: + with pytest.raises(AssertionError, match=msg): + assert_numpy_array_equal(a, other, check_same=check_same) + else: + assert_numpy_array_equal(a, other, check_same=check_same) diff --git a/pandas/tests/util/test_assert_series_equal.py b/pandas/tests/util/test_assert_series_equal.py new file mode 100644 index 0000000000000..537a0e01ff85f --- /dev/null +++ b/pandas/tests/util/test_assert_series_equal.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- + +import pytest + +from pandas import Categorical, DataFrame, Series +from pandas.util.testing import assert_series_equal + + +def _assert_series_equal_both(a, b, **kwargs): + """ + Check that two Series equal. + + This check is performed commutatively. + + Parameters + ---------- + a : Series + The first Series to compare. + b : Series + The second Series to compare. + kwargs : dict + The arguments passed to `assert_series_equal`. + """ + assert_series_equal(a, b, **kwargs) + assert_series_equal(b, a, **kwargs) + + +def _assert_not_series_equal(a, b, **kwargs): + """ + Check that two Series are not equal. + + Parameters + ---------- + a : Series + The first Series to compare. + b : Series + The second Series to compare. + kwargs : dict + The arguments passed to `assert_series_equal`. + """ + try: + assert_series_equal(a, b, **kwargs) + msg = "The two Series were equal when they shouldn't have been" + + pytest.fail(msg=msg) + except AssertionError: + pass + + +def _assert_not_series_equal_both(a, b, **kwargs): + """ + Check that two Series are not equal. + + This check is performed commutatively. + + Parameters + ---------- + a : Series + The first Series to compare. + b : Series + The second Series to compare. + kwargs : dict + The arguments passed to `assert_series_equal`. + """ + _assert_not_series_equal(a, b, **kwargs) + _assert_not_series_equal(b, a, **kwargs) + + +@pytest.mark.parametrize("data", [ + range(3), list("abc"), list(u"áàä"), +]) +def test_series_equal(data): + _assert_series_equal_both(Series(data), Series(data)) + + +@pytest.mark.parametrize("data1,data2", [ + (range(3), range(1, 4)), + (list("abc"), list("xyz")), + (list(u"áàä"), list(u"éèë")), + (list(u"áàä"), list(b"aaa")), + (range(3), range(4)), +]) +def test_series_not_equal_value_mismatch(data1, data2): + _assert_not_series_equal_both(Series(data1), Series(data2)) + + +@pytest.mark.parametrize("kwargs", [ + dict(dtype="float64"), # dtype mismatch + dict(index=[1, 2, 4]), # index mismatch + dict(name="foo"), # name mismatch +]) +def test_series_not_equal_metadata_mismatch(kwargs): + data = range(3) + s1 = Series(data) + + s2 = Series(data, **kwargs) + _assert_not_series_equal_both(s1, s2) + + +@pytest.mark.parametrize("data1,data2", [(0.12345, 0.12346), (0.1235, 0.1236)]) +@pytest.mark.parametrize("dtype", ["float32", "float64"]) +@pytest.mark.parametrize("check_less_precise", [False, True, 0, 1, 2, 3, 10]) +def test_less_precise(data1, data2, dtype, check_less_precise): + s1 = Series([data1], dtype=dtype) + s2 = Series([data2], dtype=dtype) + + kwargs = dict(check_less_precise=check_less_precise) + + if ((check_less_precise is False or check_less_precise == 10) or + ((check_less_precise is True or check_less_precise >= 3) and + abs(data1 - data2) >= 0.0001)): + msg = "Series values are different" + with pytest.raises(AssertionError, match=msg): + assert_series_equal(s1, s2, **kwargs) + else: + _assert_series_equal_both(s1, s2, **kwargs) + + +@pytest.mark.parametrize("s1,s2,msg", [ + # Index + (Series(["l1", "l2"], index=[1, 2]), + Series(["l1", "l2"], index=[1., 2.]), + "Series\\.index are different"), + + # MultiIndex + (DataFrame.from_records({"a": [1, 2], "b": [2.1, 1.5], + "c": ["l1", "l2"]}, index=["a", "b"]).c, + DataFrame.from_records({"a": [1., 2.], "b": [2.1, 1.5], + "c": ["l1", "l2"]}, index=["a", "b"]).c, + "MultiIndex level \\[0\\] are different") +]) +def test_series_equal_index_dtype(s1, s2, msg, check_index_type): + kwargs = dict(check_index_type=check_index_type) + + if check_index_type: + with pytest.raises(AssertionError, match=msg): + assert_series_equal(s1, s2, **kwargs) + else: + assert_series_equal(s1, s2, **kwargs) + + +def test_series_equal_length_mismatch(check_less_precise): + msg = """Series are different + +Series length are different +\\[left\\]: 3, RangeIndex\\(start=0, stop=3, step=1\\) +\\[right\\]: 4, RangeIndex\\(start=0, stop=4, step=1\\)""" + + s1 = Series([1, 2, 3]) + s2 = Series([1, 2, 3, 4]) + + with pytest.raises(AssertionError, match=msg): + assert_series_equal(s1, s2, check_less_precise=check_less_precise) + + +def test_series_equal_values_mismatch(check_less_precise): + msg = """Series are different + +Series values are different \\(33\\.33333 %\\) +\\[left\\]: \\[1, 2, 3\\] +\\[right\\]: \\[1, 2, 4\\]""" + + s1 = Series([1, 2, 3]) + s2 = Series([1, 2, 4]) + + with pytest.raises(AssertionError, match=msg): + assert_series_equal(s1, s2, check_less_precise=check_less_precise) + + +def test_series_equal_categorical_mismatch(check_categorical): + msg = """Attributes are different + +Attribute "dtype" are different +\\[left\\]: CategoricalDtype\\(categories=\\[u?'a', u?'b'\\], ordered=False\\) +\\[right\\]: CategoricalDtype\\(categories=\\[u?'a', u?'b', u?'c'\\], \ +ordered=False\\)""" + + s1 = Series(Categorical(["a", "b"])) + s2 = Series(Categorical(["a", "b"], categories=list("abc"))) + + if check_categorical: + with pytest.raises(AssertionError, match=msg): + assert_series_equal(s1, s2, check_categorical=check_categorical) + else: + _assert_series_equal_both(s1, s2, check_categorical=check_categorical) diff --git a/pandas/tests/util/test_testing.py b/pandas/tests/util/test_testing.py deleted file mode 100644 index e649cea14ec39..0000000000000 --- a/pandas/tests/util/test_testing.py +++ /dev/null @@ -1,984 +0,0 @@ -# -*- coding: utf-8 -*- -import os -import sys -import textwrap - -import numpy as np -import pytest - -from pandas.compat import raise_with_traceback -import pandas.util._test_decorators as td - -import pandas as pd -from pandas import DataFrame, Series, compat -from pandas.core.arrays.sparse import SparseArray -import pandas.util.testing as tm -from pandas.util.testing import ( - RNGContext, assert_almost_equal, assert_extension_array_equal, - assert_frame_equal, assert_index_equal, assert_numpy_array_equal, - assert_series_equal) - - -class TestAssertAlmostEqual(object): - - def _assert_almost_equal_both(self, a, b, **kwargs): - assert_almost_equal(a, b, **kwargs) - assert_almost_equal(b, a, **kwargs) - - def _assert_not_almost_equal_both(self, a, b, **kwargs): - pytest.raises(AssertionError, assert_almost_equal, a, b, **kwargs) - pytest.raises(AssertionError, assert_almost_equal, b, a, **kwargs) - - def test_assert_almost_equal_numbers(self): - self._assert_almost_equal_both(1.1, 1.1) - self._assert_almost_equal_both(1.1, 1.100001) - self._assert_almost_equal_both(np.int16(1), 1.000001) - self._assert_almost_equal_both(np.float64(1.1), 1.1) - self._assert_almost_equal_both(np.uint32(5), 5) - - self._assert_not_almost_equal_both(1.1, 1) - self._assert_not_almost_equal_both(1.1, True) - self._assert_not_almost_equal_both(1, 2) - self._assert_not_almost_equal_both(1.0001, np.int16(1)) - - def test_assert_almost_equal_numbers_with_zeros(self): - self._assert_almost_equal_both(0, 0) - self._assert_almost_equal_both(0, 0.0) - self._assert_almost_equal_both(0, np.float64(0)) - self._assert_almost_equal_both(0.000001, 0) - - self._assert_not_almost_equal_both(0.001, 0) - self._assert_not_almost_equal_both(1, 0) - - def test_assert_almost_equal_numbers_with_mixed(self): - self._assert_not_almost_equal_both(1, 'abc') - self._assert_not_almost_equal_both(1, [1, ]) - self._assert_not_almost_equal_both(1, object()) - - @pytest.mark.parametrize( - "left_dtype", - ['M8[ns]', 'm8[ns]', 'float64', 'int64', 'object']) - @pytest.mark.parametrize( - "right_dtype", - ['M8[ns]', 'm8[ns]', 'float64', 'int64', 'object']) - def test_assert_almost_equal_edge_case_ndarrays( - self, left_dtype, right_dtype): - - # empty compare - self._assert_almost_equal_both(np.array([], dtype=left_dtype), - np.array([], dtype=right_dtype), - check_dtype=False) - - def test_assert_almost_equal_dicts(self): - self._assert_almost_equal_both({'a': 1, 'b': 2}, {'a': 1, 'b': 2}) - - self._assert_not_almost_equal_both({'a': 1, 'b': 2}, {'a': 1, 'b': 3}) - self._assert_not_almost_equal_both({'a': 1, 'b': 2}, - {'a': 1, 'b': 2, 'c': 3}) - self._assert_not_almost_equal_both({'a': 1}, 1) - self._assert_not_almost_equal_both({'a': 1}, 'abc') - self._assert_not_almost_equal_both({'a': 1}, [1, ]) - - def test_assert_almost_equal_dict_like_object(self): - class DictLikeObj(object): - - def keys(self): - return ('a', ) - - def __getitem__(self, item): - if item == 'a': - return 1 - - self._assert_almost_equal_both({'a': 1}, DictLikeObj(), - check_dtype=False) - - self._assert_not_almost_equal_both({'a': 2}, DictLikeObj(), - check_dtype=False) - - def test_assert_almost_equal_strings(self): - self._assert_almost_equal_both('abc', 'abc') - - self._assert_not_almost_equal_both('abc', 'abcd') - self._assert_not_almost_equal_both('abc', 'abd') - self._assert_not_almost_equal_both('abc', 1) - self._assert_not_almost_equal_both('abc', [1, ]) - - def test_assert_almost_equal_iterables(self): - self._assert_almost_equal_both([1, 2, 3], [1, 2, 3]) - self._assert_almost_equal_both(np.array([1, 2, 3]), - np.array([1, 2, 3])) - - # class / dtype are different - self._assert_not_almost_equal_both(np.array([1, 2, 3]), [1, 2, 3]) - self._assert_not_almost_equal_both(np.array([1, 2, 3]), - np.array([1., 2., 3.])) - - # Can't compare generators - self._assert_not_almost_equal_both(iter([1, 2, 3]), [1, 2, 3]) - - self._assert_not_almost_equal_both([1, 2, 3], [1, 2, 4]) - self._assert_not_almost_equal_both([1, 2, 3], [1, 2, 3, 4]) - self._assert_not_almost_equal_both([1, 2, 3], 1) - - def test_assert_almost_equal_null(self): - self._assert_almost_equal_both(None, None) - - self._assert_not_almost_equal_both(None, np.NaN) - self._assert_not_almost_equal_both(None, 0) - self._assert_not_almost_equal_both(np.NaN, 0) - - def test_assert_almost_equal_inf(self): - self._assert_almost_equal_both(np.inf, np.inf) - self._assert_almost_equal_both(np.inf, float("inf")) - self._assert_not_almost_equal_both(np.inf, 0) - self._assert_almost_equal_both(np.array([np.inf, np.nan, -np.inf]), - np.array([np.inf, np.nan, -np.inf])) - self._assert_almost_equal_both(np.array([np.inf, None, -np.inf], - dtype=np.object_), - np.array([np.inf, np.nan, -np.inf], - dtype=np.object_)) - - def test_assert_almost_equal_pandas(self): - tm.assert_almost_equal(pd.Index([1., 1.1]), - pd.Index([1., 1.100001])) - tm.assert_almost_equal(pd.Series([1., 1.1]), - pd.Series([1., 1.100001])) - tm.assert_almost_equal(pd.DataFrame({'a': [1., 1.1]}), - pd.DataFrame({'a': [1., 1.100001]})) - - def test_assert_almost_equal_object(self): - a = [pd.Timestamp('2011-01-01'), pd.Timestamp('2011-01-01')] - b = [pd.Timestamp('2011-01-01'), pd.Timestamp('2011-01-01')] - self._assert_almost_equal_both(a, b) - - -class TestUtilTesting(object): - - def test_raise_with_traceback(self): - with pytest.raises(LookupError, match="error_text"): - try: - raise ValueError("THIS IS AN ERROR") - except ValueError as e: - e = LookupError("error_text") - raise_with_traceback(e) - with pytest.raises(LookupError, match="error_text"): - try: - raise ValueError("This is another error") - except ValueError: - e = LookupError("error_text") - _, _, traceback = sys.exc_info() - raise_with_traceback(e, traceback) - - def test_convert_rows_list_to_csv_str(self): - rows_list = ["aaa", "bbb", "ccc"] - ret = tm.convert_rows_list_to_csv_str(rows_list) - - if compat.is_platform_windows(): - expected = "aaa\r\nbbb\r\nccc\r\n" - else: - expected = "aaa\nbbb\nccc\n" - - assert ret == expected - - -class TestAssertNumpyArrayEqual(object): - - @td.skip_if_windows - def test_numpy_array_equal_message(self): - - expected = """numpy array are different - -numpy array shapes are different -\\[left\\]: \\(2,\\) -\\[right\\]: \\(3,\\)""" - - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal(np.array([1, 2]), np.array([3, 4, 5])) - - with pytest.raises(AssertionError, match=expected): - assert_almost_equal(np.array([1, 2]), np.array([3, 4, 5])) - - # scalar comparison - expected = """Expected type """ - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal(1, 2) - expected = """expected 2\\.00000 but got 1\\.00000, with decimal 5""" - with pytest.raises(AssertionError, match=expected): - assert_almost_equal(1, 2) - - # array / scalar array comparison - expected = """numpy array are different - -numpy array classes are different -\\[left\\]: ndarray -\\[right\\]: int""" - - with pytest.raises(AssertionError, match=expected): - # numpy_array_equal only accepts np.ndarray - assert_numpy_array_equal(np.array([1]), 1) - with pytest.raises(AssertionError, match=expected): - assert_almost_equal(np.array([1]), 1) - - # scalar / array comparison - expected = """numpy array are different - -numpy array classes are different -\\[left\\]: int -\\[right\\]: ndarray""" - - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal(1, np.array([1])) - with pytest.raises(AssertionError, match=expected): - assert_almost_equal(1, np.array([1])) - - expected = """numpy array are different - -numpy array values are different \\(66\\.66667 %\\) -\\[left\\]: \\[nan, 2\\.0, 3\\.0\\] -\\[right\\]: \\[1\\.0, nan, 3\\.0\\]""" - - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal(np.array([np.nan, 2, 3]), - np.array([1, np.nan, 3])) - with pytest.raises(AssertionError, match=expected): - assert_almost_equal(np.array([np.nan, 2, 3]), - np.array([1, np.nan, 3])) - - expected = """numpy array are different - -numpy array values are different \\(50\\.0 %\\) -\\[left\\]: \\[1, 2\\] -\\[right\\]: \\[1, 3\\]""" - - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal(np.array([1, 2]), np.array([1, 3])) - with pytest.raises(AssertionError, match=expected): - assert_almost_equal(np.array([1, 2]), np.array([1, 3])) - - expected = """numpy array are different - -numpy array values are different \\(50\\.0 %\\) -\\[left\\]: \\[1\\.1, 2\\.000001\\] -\\[right\\]: \\[1\\.1, 2.0\\]""" - - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal( - np.array([1.1, 2.000001]), np.array([1.1, 2.0])) - - # must pass - assert_almost_equal(np.array([1.1, 2.000001]), np.array([1.1, 2.0])) - - expected = """numpy array are different - -numpy array values are different \\(16\\.66667 %\\) -\\[left\\]: \\[\\[1, 2\\], \\[3, 4\\], \\[5, 6\\]\\] -\\[right\\]: \\[\\[1, 3\\], \\[3, 4\\], \\[5, 6\\]\\]""" - - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal(np.array([[1, 2], [3, 4], [5, 6]]), - np.array([[1, 3], [3, 4], [5, 6]])) - with pytest.raises(AssertionError, match=expected): - assert_almost_equal(np.array([[1, 2], [3, 4], [5, 6]]), - np.array([[1, 3], [3, 4], [5, 6]])) - - expected = """numpy array are different - -numpy array values are different \\(25\\.0 %\\) -\\[left\\]: \\[\\[1, 2\\], \\[3, 4\\]\\] -\\[right\\]: \\[\\[1, 3\\], \\[3, 4\\]\\]""" - - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal(np.array([[1, 2], [3, 4]]), - np.array([[1, 3], [3, 4]])) - with pytest.raises(AssertionError, match=expected): - assert_almost_equal(np.array([[1, 2], [3, 4]]), - np.array([[1, 3], [3, 4]])) - - # allow to overwrite message - expected = """Index are different - -Index shapes are different -\\[left\\]: \\(2,\\) -\\[right\\]: \\(3,\\)""" - - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal(np.array([1, 2]), np.array([3, 4, 5]), - obj='Index') - with pytest.raises(AssertionError, match=expected): - assert_almost_equal(np.array([1, 2]), np.array([3, 4, 5]), - obj='Index') - - def test_numpy_array_equal_unicode_message(self): - # Test ensures that `assert_numpy_array_equals` raises the right - # exception when comparing np.arrays containing differing - # unicode objects (#20503) - - expected = """numpy array are different - -numpy array values are different \\(33\\.33333 %\\) -\\[left\\]: \\[á, à, ä\\] -\\[right\\]: \\[á, à, å\\]""" - - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal(np.array([u'á', u'à', u'ä']), - np.array([u'á', u'à', u'å'])) - with pytest.raises(AssertionError, match=expected): - assert_almost_equal(np.array([u'á', u'à', u'ä']), - np.array([u'á', u'à', u'å'])) - - @td.skip_if_windows - def test_numpy_array_equal_object_message(self): - - a = np.array([pd.Timestamp('2011-01-01'), pd.Timestamp('2011-01-01')]) - b = np.array([pd.Timestamp('2011-01-01'), pd.Timestamp('2011-01-02')]) - - expected = """numpy array are different - -numpy array values are different \\(50\\.0 %\\) -\\[left\\]: \\[2011-01-01 00:00:00, 2011-01-01 00:00:00\\] -\\[right\\]: \\[2011-01-01 00:00:00, 2011-01-02 00:00:00\\]""" - - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal(a, b) - with pytest.raises(AssertionError, match=expected): - assert_almost_equal(a, b) - - def test_numpy_array_equal_copy_flag(self): - a = np.array([1, 2, 3]) - b = a.copy() - c = a.view() - expected = r'array\(\[1, 2, 3\]\) is not array\(\[1, 2, 3\]\)' - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal(a, b, check_same='same') - expected = r'array\(\[1, 2, 3\]\) is array\(\[1, 2, 3\]\)' - with pytest.raises(AssertionError, match=expected): - assert_numpy_array_equal(a, c, check_same='copy') - - def test_assert_almost_equal_iterable_message(self): - - expected = """Iterable are different - -Iterable length are different -\\[left\\]: 2 -\\[right\\]: 3""" - - with pytest.raises(AssertionError, match=expected): - assert_almost_equal([1, 2], [3, 4, 5]) - - expected = """Iterable are different - -Iterable values are different \\(50\\.0 %\\) -\\[left\\]: \\[1, 2\\] -\\[right\\]: \\[1, 3\\]""" - - with pytest.raises(AssertionError, match=expected): - assert_almost_equal([1, 2], [1, 3]) - - -class TestAssertIndexEqual(object): - - def test_index_equal_message(self): - - expected = """Index are different - -Index levels are different -\\[left\\]: 1, Int64Index\\(\\[1, 2, 3\\], dtype='int64'\\) -\\[right\\]: 2, MultiIndex\\(levels=\\[\\[u?'A', u?'B'\\], \\[1, 2, 3, 4\\]\\], - labels=\\[\\[0, 0, 1, 1\\], \\[0, 1, 2, 3\\]\\]\\)""" - - idx1 = pd.Index([1, 2, 3]) - idx2 = pd.MultiIndex.from_tuples([('A', 1), ('A', 2), - ('B', 3), ('B', 4)]) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2, exact=False) - - expected = """MultiIndex level \\[1\\] are different - -MultiIndex level \\[1\\] values are different \\(25\\.0 %\\) -\\[left\\]: Int64Index\\(\\[2, 2, 3, 4\\], dtype='int64'\\) -\\[right\\]: Int64Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)""" - - idx1 = pd.MultiIndex.from_tuples([('A', 2), ('A', 2), - ('B', 3), ('B', 4)]) - idx2 = pd.MultiIndex.from_tuples([('A', 1), ('A', 2), - ('B', 3), ('B', 4)]) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2, check_exact=False) - - expected = """Index are different - -Index length are different -\\[left\\]: 3, Int64Index\\(\\[1, 2, 3\\], dtype='int64'\\) -\\[right\\]: 4, Int64Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)""" - - idx1 = pd.Index([1, 2, 3]) - idx2 = pd.Index([1, 2, 3, 4]) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2, check_exact=False) - - expected = """Index are different - -Index classes are different -\\[left\\]: Int64Index\\(\\[1, 2, 3\\], dtype='int64'\\) -\\[right\\]: Float64Index\\(\\[1\\.0, 2\\.0, 3\\.0\\], dtype='float64'\\)""" - - idx1 = pd.Index([1, 2, 3]) - idx2 = pd.Index([1, 2, 3.0]) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2, exact=True) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2, exact=True, check_exact=False) - - expected = """Index are different - -Index values are different \\(33\\.33333 %\\) -\\[left\\]: Float64Index\\(\\[1.0, 2.0, 3.0], dtype='float64'\\) -\\[right\\]: Float64Index\\(\\[1.0, 2.0, 3.0000000001\\], dtype='float64'\\)""" - - idx1 = pd.Index([1, 2, 3.]) - idx2 = pd.Index([1, 2, 3.0000000001]) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2) - - # must success - assert_index_equal(idx1, idx2, check_exact=False) - - expected = """Index are different - -Index values are different \\(33\\.33333 %\\) -\\[left\\]: Float64Index\\(\\[1.0, 2.0, 3.0], dtype='float64'\\) -\\[right\\]: Float64Index\\(\\[1.0, 2.0, 3.0001\\], dtype='float64'\\)""" - - idx1 = pd.Index([1, 2, 3.]) - idx2 = pd.Index([1, 2, 3.0001]) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2, check_exact=False) - # must success - assert_index_equal(idx1, idx2, check_exact=False, - check_less_precise=True) - - expected = """Index are different - -Index values are different \\(33\\.33333 %\\) -\\[left\\]: Int64Index\\(\\[1, 2, 3\\], dtype='int64'\\) -\\[right\\]: Int64Index\\(\\[1, 2, 4\\], dtype='int64'\\)""" - - idx1 = pd.Index([1, 2, 3]) - idx2 = pd.Index([1, 2, 4]) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2, check_less_precise=True) - - expected = """MultiIndex level \\[1\\] are different - -MultiIndex level \\[1\\] values are different \\(25\\.0 %\\) -\\[left\\]: Int64Index\\(\\[2, 2, 3, 4\\], dtype='int64'\\) -\\[right\\]: Int64Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)""" - - idx1 = pd.MultiIndex.from_tuples([('A', 2), ('A', 2), - ('B', 3), ('B', 4)]) - idx2 = pd.MultiIndex.from_tuples([('A', 1), ('A', 2), - ('B', 3), ('B', 4)]) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2, check_exact=False) - - def test_index_equal_metadata_message(self): - - expected = """Index are different - -Attribute "names" are different -\\[left\\]: \\[None\\] -\\[right\\]: \\[u?'x'\\]""" - - idx1 = pd.Index([1, 2, 3]) - idx2 = pd.Index([1, 2, 3], name='x') - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2) - - # same name, should pass - assert_index_equal(pd.Index([1, 2, 3], name=np.nan), - pd.Index([1, 2, 3], name=np.nan)) - assert_index_equal(pd.Index([1, 2, 3], name=pd.NaT), - pd.Index([1, 2, 3], name=pd.NaT)) - - expected = """Index are different - -Attribute "names" are different -\\[left\\]: \\[nan\\] -\\[right\\]: \\[NaT\\]""" - - idx1 = pd.Index([1, 2, 3], name=np.nan) - idx2 = pd.Index([1, 2, 3], name=pd.NaT) - with pytest.raises(AssertionError, match=expected): - assert_index_equal(idx1, idx2) - - def test_categorical_index_equality(self): - expected = """Index are different - -Attribute "dtype" are different -\\[left\\]: CategoricalDtype\\(categories=\\[u?'a', u?'b'\\], ordered=False\\) -\\[right\\]: CategoricalDtype\\(categories=\\[u?'a', u?'b', u?'c'\\], \ -ordered=False\\)""" - - with pytest.raises(AssertionError, match=expected): - assert_index_equal(pd.Index(pd.Categorical(['a', 'b'])), - pd.Index(pd.Categorical(['a', 'b'], - categories=['a', 'b', 'c']))) - - def test_categorical_index_equality_relax_categories_check(self): - assert_index_equal(pd.Index(pd.Categorical(['a', 'b'])), - pd.Index(pd.Categorical(['a', 'b'], - categories=['a', 'b', 'c'])), - check_categorical=False) - - -class TestAssertSeriesEqual(object): - - def _assert_equal(self, x, y, **kwargs): - assert_series_equal(x, y, **kwargs) - assert_series_equal(y, x, **kwargs) - - def _assert_not_equal(self, a, b, **kwargs): - pytest.raises(AssertionError, assert_series_equal, a, b, **kwargs) - pytest.raises(AssertionError, assert_series_equal, b, a, **kwargs) - - def test_equal(self): - self._assert_equal(Series(range(3)), Series(range(3))) - self._assert_equal(Series(list('abc')), Series(list('abc'))) - self._assert_equal(Series(list(u'áàä')), Series(list(u'áàä'))) - - def test_not_equal(self): - self._assert_not_equal(Series(range(3)), Series(range(3)) + 1) - self._assert_not_equal(Series(list('abc')), Series(list('xyz'))) - self._assert_not_equal(Series(list(u'áàä')), Series(list(u'éèë'))) - self._assert_not_equal(Series(list(u'áàä')), Series(list(b'aaa'))) - self._assert_not_equal(Series(range(3)), Series(range(4))) - self._assert_not_equal( - Series(range(3)), Series( - range(3), dtype='float64')) - self._assert_not_equal( - Series(range(3)), Series( - range(3), index=[1, 2, 4])) - - # ATM meta data is not checked in assert_series_equal - # self._assert_not_equal(Series(range(3)),Series(range(3),name='foo'),check_names=True) - - def test_less_precise(self): - s1 = Series([0.12345], dtype='float64') - s2 = Series([0.12346], dtype='float64') - - pytest.raises(AssertionError, assert_series_equal, s1, s2) - self._assert_equal(s1, s2, check_less_precise=True) - for i in range(4): - self._assert_equal(s1, s2, check_less_precise=i) - pytest.raises(AssertionError, assert_series_equal, s1, s2, 10) - - s1 = Series([0.12345], dtype='float32') - s2 = Series([0.12346], dtype='float32') - - pytest.raises(AssertionError, assert_series_equal, s1, s2) - self._assert_equal(s1, s2, check_less_precise=True) - for i in range(4): - self._assert_equal(s1, s2, check_less_precise=i) - pytest.raises(AssertionError, assert_series_equal, s1, s2, 10) - - # even less than less precise - s1 = Series([0.1235], dtype='float32') - s2 = Series([0.1236], dtype='float32') - - pytest.raises(AssertionError, assert_series_equal, s1, s2) - pytest.raises(AssertionError, assert_series_equal, s1, s2, True) - - def test_index_dtype(self): - df1 = DataFrame.from_records( - {'a': [1, 2], 'c': ['l1', 'l2']}, index=['a']) - df2 = DataFrame.from_records( - {'a': [1.0, 2.0], 'c': ['l1', 'l2']}, index=['a']) - self._assert_not_equal(df1.c, df2.c, check_index_type=True) - - def test_multiindex_dtype(self): - df1 = DataFrame.from_records( - {'a': [1, 2], 'b': [2.1, 1.5], - 'c': ['l1', 'l2']}, index=['a', 'b']) - df2 = DataFrame.from_records( - {'a': [1.0, 2.0], 'b': [2.1, 1.5], - 'c': ['l1', 'l2']}, index=['a', 'b']) - self._assert_not_equal(df1.c, df2.c, check_index_type=True) - - def test_series_equal_message(self): - - expected = """Series are different - -Series length are different -\\[left\\]: 3, RangeIndex\\(start=0, stop=3, step=1\\) -\\[right\\]: 4, RangeIndex\\(start=0, stop=4, step=1\\)""" - - with pytest.raises(AssertionError, match=expected): - assert_series_equal(pd.Series([1, 2, 3]), pd.Series([1, 2, 3, 4])) - - expected = """Series are different - -Series values are different \\(33\\.33333 %\\) -\\[left\\]: \\[1, 2, 3\\] -\\[right\\]: \\[1, 2, 4\\]""" - - with pytest.raises(AssertionError, match=expected): - assert_series_equal(pd.Series([1, 2, 3]), pd.Series([1, 2, 4])) - with pytest.raises(AssertionError, match=expected): - assert_series_equal(pd.Series([1, 2, 3]), pd.Series([1, 2, 4]), - check_less_precise=True) - - def test_categorical_series_equality(self): - expected = """Attributes are different - -Attribute "dtype" are different -\\[left\\]: CategoricalDtype\\(categories=\\[u?'a', u?'b'\\], ordered=False\\) -\\[right\\]: CategoricalDtype\\(categories=\\[u?'a', u?'b', u?'c'\\], \ -ordered=False\\)""" - - with pytest.raises(AssertionError, match=expected): - assert_series_equal(pd.Series(pd.Categorical(['a', 'b'])), - pd.Series(pd.Categorical(['a', 'b'], - categories=['a', 'b', 'c']))) - - def test_categorical_series_equality_relax_categories_check(self): - assert_series_equal(pd.Series(pd.Categorical(['a', 'b'])), - pd.Series(pd.Categorical(['a', 'b'], - categories=['a', 'b', 'c'])), - check_categorical=False) - - -class TestAssertFrameEqual(object): - - def _assert_equal(self, x, y, **kwargs): - assert_frame_equal(x, y, **kwargs) - assert_frame_equal(y, x, **kwargs) - - def _assert_not_equal(self, a, b, **kwargs): - pytest.raises(AssertionError, assert_frame_equal, a, b, **kwargs) - pytest.raises(AssertionError, assert_frame_equal, b, a, **kwargs) - - def test_equal_with_different_row_order(self): - # check_like=True ignores row-column orderings - df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}, - index=['a', 'b', 'c']) - df2 = pd.DataFrame({'A': [3, 2, 1], 'B': [6, 5, 4]}, - index=['c', 'b', 'a']) - - self._assert_equal(df1, df2, check_like=True) - self._assert_not_equal(df1, df2) - - def test_not_equal_with_different_shape(self): - self._assert_not_equal(pd.DataFrame({'A': [1, 2, 3]}), - pd.DataFrame({'A': [1, 2, 3, 4]})) - - def test_index_dtype(self): - df1 = DataFrame.from_records( - {'a': [1, 2], 'c': ['l1', 'l2']}, index=['a']) - df2 = DataFrame.from_records( - {'a': [1.0, 2.0], 'c': ['l1', 'l2']}, index=['a']) - self._assert_not_equal(df1, df2, check_index_type=True) - - def test_multiindex_dtype(self): - df1 = DataFrame.from_records( - {'a': [1, 2], 'b': [2.1, 1.5], - 'c': ['l1', 'l2']}, index=['a', 'b']) - df2 = DataFrame.from_records( - {'a': [1.0, 2.0], 'b': [2.1, 1.5], - 'c': ['l1', 'l2']}, index=['a', 'b']) - self._assert_not_equal(df1, df2, check_index_type=True) - - def test_empty_dtypes(self): - df1 = pd.DataFrame(columns=["col1", "col2"]) - df1["col1"] = df1["col1"].astype('int64') - df2 = pd.DataFrame(columns=["col1", "col2"]) - self._assert_equal(df1, df2, check_dtype=False) - self._assert_not_equal(df1, df2, check_dtype=True) - - def test_frame_equal_message(self): - - expected = """DataFrame are different - -DataFrame shape mismatch -\\[left\\]: \\(3, 2\\) -\\[right\\]: \\(3, 1\\)""" - - with pytest.raises(AssertionError, match=expected): - assert_frame_equal(pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}), - pd.DataFrame({'A': [1, 2, 3]})) - - expected = """DataFrame\\.index are different - -DataFrame\\.index values are different \\(33\\.33333 %\\) -\\[left\\]: Index\\(\\[u?'a', u?'b', u?'c'\\], dtype='object'\\) -\\[right\\]: Index\\(\\[u?'a', u?'b', u?'d'\\], dtype='object'\\)""" - - with pytest.raises(AssertionError, match=expected): - assert_frame_equal(pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}, - index=['a', 'b', 'c']), - pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}, - index=['a', 'b', 'd'])) - - expected = """DataFrame\\.columns are different - -DataFrame\\.columns values are different \\(50\\.0 %\\) -\\[left\\]: Index\\(\\[u?'A', u?'B'\\], dtype='object'\\) -\\[right\\]: Index\\(\\[u?'A', u?'b'\\], dtype='object'\\)""" - - with pytest.raises(AssertionError, match=expected): - assert_frame_equal(pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}, - index=['a', 'b', 'c']), - pd.DataFrame({'A': [1, 2, 3], 'b': [4, 5, 6]}, - index=['a', 'b', 'c'])) - - expected = """DataFrame\\.iloc\\[:, 1\\] are different - -DataFrame\\.iloc\\[:, 1\\] values are different \\(33\\.33333 %\\) -\\[left\\]: \\[4, 5, 6\\] -\\[right\\]: \\[4, 5, 7\\]""" - - with pytest.raises(AssertionError, match=expected): - assert_frame_equal(pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}), - pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 7]})) - - with pytest.raises(AssertionError, match=expected): - assert_frame_equal(pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}), - pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 7]}), - by_blocks=True) - - def test_frame_equal_message_unicode(self): - # Test ensures that `assert_frame_equals` raises the right - # exception when comparing DataFrames containing differing - # unicode objects (#20503) - - expected = """DataFrame\\.iloc\\[:, 1\\] are different - -DataFrame\\.iloc\\[:, 1\\] values are different \\(33\\.33333 %\\) -\\[left\\]: \\[é, è, ë\\] -\\[right\\]: \\[é, è, e̊\\]""" - - with pytest.raises(AssertionError, match=expected): - assert_frame_equal(pd.DataFrame({'A': [u'á', u'à', u'ä'], - 'E': [u'é', u'è', u'ë']}), - pd.DataFrame({'A': [u'á', u'à', u'ä'], - 'E': [u'é', u'è', u'e̊']})) - - with pytest.raises(AssertionError, match=expected): - assert_frame_equal(pd.DataFrame({'A': [u'á', u'à', u'ä'], - 'E': [u'é', u'è', u'ë']}), - pd.DataFrame({'A': [u'á', u'à', u'ä'], - 'E': [u'é', u'è', u'e̊']}), - by_blocks=True) - - expected = """DataFrame\\.iloc\\[:, 0\\] are different - -DataFrame\\.iloc\\[:, 0\\] values are different \\(100\\.0 %\\) -\\[left\\]: \\[á, à, ä\\] -\\[right\\]: \\[a, a, a\\]""" - - with pytest.raises(AssertionError, match=expected): - assert_frame_equal(pd.DataFrame({'A': [u'á', u'à', u'ä'], - 'E': [u'é', u'è', u'ë']}), - pd.DataFrame({'A': ['a', 'a', 'a'], - 'E': ['e', 'e', 'e']})) - - with pytest.raises(AssertionError, match=expected): - assert_frame_equal(pd.DataFrame({'A': [u'á', u'à', u'ä'], - 'E': [u'é', u'è', u'ë']}), - pd.DataFrame({'A': ['a', 'a', 'a'], - 'E': ['e', 'e', 'e']}), - by_blocks=True) - - -class TestAssertCategoricalEqual(object): - - def test_categorical_equal_message(self): - - expected = """Categorical\\.categories are different - -Categorical\\.categories values are different \\(25\\.0 %\\) -\\[left\\]: Int64Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\) -\\[right\\]: Int64Index\\(\\[1, 2, 3, 5\\], dtype='int64'\\)""" - - a = pd.Categorical([1, 2, 3, 4]) - b = pd.Categorical([1, 2, 3, 5]) - with pytest.raises(AssertionError, match=expected): - tm.assert_categorical_equal(a, b) - - expected = """Categorical\\.codes are different - -Categorical\\.codes values are different \\(50\\.0 %\\) -\\[left\\]: \\[0, 1, 3, 2\\] -\\[right\\]: \\[0, 1, 2, 3\\]""" - - a = pd.Categorical([1, 2, 4, 3], categories=[1, 2, 3, 4]) - b = pd.Categorical([1, 2, 3, 4], categories=[1, 2, 3, 4]) - with pytest.raises(AssertionError, match=expected): - tm.assert_categorical_equal(a, b) - - expected = """Categorical are different - -Attribute "ordered" are different -\\[left\\]: False -\\[right\\]: True""" - - a = pd.Categorical([1, 2, 3, 4], ordered=False) - b = pd.Categorical([1, 2, 3, 4], ordered=True) - with pytest.raises(AssertionError, match=expected): - tm.assert_categorical_equal(a, b) - - -class TestAssertIntervalArrayEqual(object): - def test_interval_array_equal_message(self): - a = pd.interval_range(0, periods=4).values - b = pd.interval_range(1, periods=4).values - - msg = textwrap.dedent("""\ - IntervalArray.left are different - - IntervalArray.left values are different \\(100.0 %\\) - \\[left\\]: Int64Index\\(\\[0, 1, 2, 3\\], dtype='int64'\\) - \\[right\\]: Int64Index\\(\\[1, 2, 3, 4\\], dtype='int64'\\)""") - with pytest.raises(AssertionError, match=msg): - tm.assert_interval_array_equal(a, b) - - -class TestAssertExtensionArrayEqual(object): - - def test_check_exact(self): - # GH 23709 - left = SparseArray([-0.17387645482451206, 0.3414148016424936]) - right = SparseArray([-0.17387645482451206, 0.3414148016424937]) - - # passes with check_exact=False (should be default) - assert_extension_array_equal(left, right) - assert_extension_array_equal(left, right, check_exact=False) - - # raises with check_exact=True - msg = textwrap.dedent("""\ - ExtensionArray are different - - ExtensionArray values are different \\(50\\.0 %\\) - \\[left\\]: \\[-0\\.17387645482.*, 0\\.341414801642.*\\] - \\[right\\]: \\[-0\\.17387645482.*, 0\\.341414801642.*\\]""") - with pytest.raises(AssertionError, match=msg): - assert_extension_array_equal(left, right, check_exact=True) - - @pytest.mark.parametrize('check_less_precise', [True, 0, 1, 2, 3, 4]) - def test_check_less_precise_passes(self, check_less_precise): - left = SparseArray([0.5, 0.123456]) - right = SparseArray([0.5, 0.123457]) - assert_extension_array_equal( - left, right, check_less_precise=check_less_precise) - - @pytest.mark.parametrize('check_less_precise', [False, 5, 6, 7, 8, 9]) - def test_check_less_precise_fails(self, check_less_precise): - left = SparseArray([0.5, 0.123456]) - right = SparseArray([0.5, 0.123457]) - - msg = textwrap.dedent("""\ - ExtensionArray are different - - ExtensionArray values are different \\(50\\.0 %\\) - \\[left\\]: \\[0\\.5, 0\\.123456\\] - \\[right\\]: \\[0\\.5, 0\\.123457\\]""") - with pytest.raises(AssertionError, match=msg): - assert_extension_array_equal( - left, right, check_less_precise=check_less_precise) - - def test_check_dtype(self): - left = SparseArray(np.arange(5, dtype='int64')) - right = SparseArray(np.arange(5, dtype='int32')) - - # passes with check_dtype=False - assert_extension_array_equal(left, right, check_dtype=False) - - # raises with check_dtype=True - msg = textwrap.dedent("""\ - ExtensionArray are different - - Attribute "dtype" are different - \\[left\\]: Sparse\\[int64, 0\\] - \\[right\\]: Sparse\\[int32, 0\\]""") - with pytest.raises(AssertionError, match=msg): - assert_extension_array_equal(left, right, check_dtype=True) - - def test_missing_values(self): - left = SparseArray([np.nan, 1, 2, np.nan]) - right = SparseArray([np.nan, 1, 2, 3]) - - msg = textwrap.dedent("""\ - ExtensionArray NA mask are different - - ExtensionArray NA mask values are different \\(25\\.0 %\\) - \\[left\\]: \\[True, False, False, True\\] - \\[right\\]: \\[True, False, False, False\\]""") - with pytest.raises(AssertionError, match=msg): - assert_extension_array_equal(left, right) - - def test_non_extension_array(self): - numpy_array = np.arange(5) - extension_array = SparseArray(np.arange(5)) - - msg = 'left is not an ExtensionArray' - with pytest.raises(AssertionError, match=msg): - assert_extension_array_equal(numpy_array, extension_array) - - msg = 'right is not an ExtensionArray' - with pytest.raises(AssertionError, match=msg): - assert_extension_array_equal(extension_array, numpy_array) - - -class TestRNGContext(object): - - def test_RNGContext(self): - expected0 = 1.764052345967664 - expected1 = 1.6243453636632417 - - with RNGContext(0): - with RNGContext(1): - assert np.random.randn() == expected1 - assert np.random.randn() == expected0 - - -def test_datapath_missing(datapath, request): - if not request.config.getoption("--strict-data-files"): - pytest.skip("Need to set '--strict-data-files'") - - with pytest.raises(ValueError): - datapath('not_a_file') - - result = datapath('data', 'iris.csv') - expected = os.path.join( - os.path.dirname(os.path.dirname(__file__)), - 'data', - 'iris.csv' - ) - - assert result == expected - - -def test_create_temp_directory(): - with tm.ensure_clean_dir() as path: - assert os.path.exists(path) - assert os.path.isdir(path) - assert not os.path.exists(path) - - -def test_assert_raises_regex_deprecated(): - # see gh-23592 - - with tm.assert_produces_warning(FutureWarning): - msg = "Not equal!" - - with tm.assert_raises_regex(AssertionError, msg): - assert 1 == 2, msg diff --git a/pandas/tests/util/test_util.py b/pandas/tests/util/test_util.py index e4b2f0a75051a..f9282ff15612d 100644 --- a/pandas/tests/util/test_util.py +++ b/pandas/tests/util/test_util.py @@ -1,6 +1,11 @@ # -*- coding: utf-8 -*- +import os +import sys + import pytest +import pandas.compat as compat +from pandas.compat import raise_with_traceback from pandas.util._decorators import deprecate_kwarg, make_signature from pandas.util._validators import validate_kwargs @@ -9,19 +14,19 @@ def test_rands(): r = tm.rands(10) - assert(len(r) == 10) + assert len(r) == 10 def test_rands_array_1d(): arr = tm.rands_array(5, size=10) - assert(arr.shape == (10,)) - assert(len(arr[0]) == 5) + assert arr.shape == (10,) + assert len(arr[0]) == 5 def test_rands_array_2d(): arr = tm.rands_array(7, size=(10, 10)) - assert(arr.shape == (10, 10)) - assert(len(arr[1, 1]) == 7) + assert arr.shape == (10, 10) + assert len(arr[1, 1]) == 7 def test_numpy_err_state_is_default(): @@ -48,3 +53,76 @@ def test_numpy_err_state_is_default(): def test_make_signature(func, expected): # see gh-17608 assert make_signature(func) == expected + + +def test_raise_with_traceback(): + with pytest.raises(LookupError, match="error_text"): + try: + raise ValueError("THIS IS AN ERROR") + except ValueError: + e = LookupError("error_text") + raise_with_traceback(e) + + with pytest.raises(LookupError, match="error_text"): + try: + raise ValueError("This is another error") + except ValueError: + e = LookupError("error_text") + _, _, traceback = sys.exc_info() + raise_with_traceback(e, traceback) + + +def test_convert_rows_list_to_csv_str(): + rows_list = ["aaa", "bbb", "ccc"] + ret = tm.convert_rows_list_to_csv_str(rows_list) + + if compat.is_platform_windows(): + expected = "aaa\r\nbbb\r\nccc\r\n" + else: + expected = "aaa\nbbb\nccc\n" + + assert ret == expected + + +def test_create_temp_directory(): + with tm.ensure_clean_dir() as path: + assert os.path.exists(path) + assert os.path.isdir(path) + assert not os.path.exists(path) + + +def test_assert_raises_regex_deprecated(): + # see gh-23592 + + with tm.assert_produces_warning(FutureWarning): + msg = "Not equal!" + + with tm.assert_raises_regex(AssertionError, msg): + assert 1 == 2, msg + + +def test_datapath_missing(datapath, request): + if not request.config.getoption("--strict-data-files"): + pytest.skip("Need to set '--strict-data-files'") + + with pytest.raises(ValueError, match="Could not find file"): + datapath("not_a_file") + + args = ("data", "iris.csv") + + result = datapath(*args) + expected = os.path.join(os.path.dirname(os.path.dirname(__file__)), *args) + + assert result == expected + + +def test_rng_context(): + import numpy as np + + expected0 = 1.764052345967664 + expected1 = 1.6243453636632417 + + with tm.RNGContext(0): + with tm.RNGContext(1): + assert np.random.randn() == expected1 + assert np.random.randn() == expected0