Skip to content

Commit 37b5800

Browse files
authored
TST: tighten PandasArray tests (#39370)
1 parent caf81fa commit 37b5800

File tree

1 file changed

+45
-63
lines changed

1 file changed

+45
-63
lines changed

pandas/tests/extension/test_numpy.py

+45-63
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import numpy as np
1717
import pytest
1818

19+
from pandas.core.dtypes.dtypes import ExtensionDtype
20+
1921
import pandas as pd
2022
import pandas._testing as tm
2123
from pandas.core.arrays.numpy_ import PandasArray, PandasDtype
@@ -121,7 +123,7 @@ def data_for_grouping(allow_in_pandas, dtype):
121123

122124

123125
@pytest.fixture
124-
def skip_numpy_object(dtype):
126+
def skip_numpy_object(dtype, request):
125127
"""
126128
Tests for PandasArray with nested data. Users typically won't create
127129
these objects via `pd.array`, but they can show up through `.array`
@@ -132,14 +134,25 @@ def skip_numpy_object(dtype):
132134
marker to either an individual test or a test class.
133135
"""
134136
if dtype == "object":
135-
raise pytest.skip("Skipping for object dtype.")
137+
mark = pytest.mark.xfail(reason="Fails for object dtype")
138+
request.node.add_marker(mark)
136139

137140

138141
skip_nested = pytest.mark.usefixtures("skip_numpy_object")
139142

140143

141144
class BaseNumPyTests:
142-
pass
145+
@classmethod
146+
def assert_series_equal(cls, left, right, *args, **kwargs):
147+
# base class tests hard-code expected values with numpy dtypes,
148+
# whereas we generally want the corresponding PandasDtype
149+
if (
150+
isinstance(right, pd.Series)
151+
and not isinstance(right.dtype, ExtensionDtype)
152+
and isinstance(left.dtype, PandasDtype)
153+
):
154+
right = right.astype(PandasDtype(right.dtype))
155+
return tm.assert_series_equal(left, right, *args, **kwargs)
143156

144157

145158
class TestCasting(BaseNumPyTests, base.BaseCastingTests):
@@ -148,24 +161,13 @@ def test_astype_str(self, data):
148161
# ValueError: setting an array element with a sequence
149162
super().test_astype_str(data)
150163

151-
@skip_nested
152-
def test_astype_string(self, data):
153-
# GH-33465
154-
# ValueError: setting an array element with a sequence
155-
super().test_astype_string(data)
156-
157164

158165
class TestConstructors(BaseNumPyTests, base.BaseConstructorsTests):
159166
@pytest.mark.skip(reason="We don't register our dtype")
160167
# We don't want to register. This test should probably be split in two.
161168
def test_from_dtype(self, data):
162169
pass
163170

164-
@skip_nested
165-
def test_array_from_scalars(self, data):
166-
# ValueError: PandasArray must be 1-dimensional.
167-
super().test_array_from_scalars(data)
168-
169171
@skip_nested
170172
def test_series_constructor_scalar_with_index(self, data, dtype):
171173
# ValueError: Length of passed values is 1, index implies 3.
@@ -202,10 +204,16 @@ def test_loc_iloc_frame_single_dtype(self, data, request):
202204

203205

204206
class TestGroupby(BaseNumPyTests, base.BaseGroupbyTests):
205-
@skip_nested
206207
def test_groupby_extension_apply(
207208
self, data_for_grouping, groupby_apply_op, request
208209
):
210+
dummy = groupby_apply_op([None])
211+
if (
212+
isinstance(dummy, pd.Series)
213+
and data_for_grouping.dtype.numpy_dtype == object
214+
):
215+
mark = pytest.mark.xfail(reason="raises in MultiIndex construction")
216+
request.node.add_marker(mark)
209217
super().test_groupby_extension_apply(data_for_grouping, groupby_apply_op)
210218

211219

@@ -225,17 +233,6 @@ def test_value_counts(self, all_data, dropna):
225233
def test_value_counts_with_normalize(self, data):
226234
return super().test_value_counts_with_normalize(data)
227235

228-
@pytest.mark.skip(reason="Incorrect expected")
229-
# We have a bool dtype, so the result is an ExtensionArray
230-
# but expected is not
231-
def test_combine_le(self, data_repeated):
232-
super().test_combine_le(data_repeated)
233-
234-
@skip_nested
235-
def test_combine_add(self, data_repeated):
236-
# Not numeric
237-
super().test_combine_add(data_repeated)
238-
239236
@skip_nested
240237
def test_shift_fill_value(self, data):
241238
# np.array shape inference. Shift implementation fails.
@@ -258,11 +255,6 @@ def test_fillna_copy_series(self, data_missing):
258255
# The "scalar" for this array isn't a scalar.
259256
super().test_fillna_copy_series(data_missing)
260257

261-
@skip_nested
262-
def test_hash_pandas_object_works(self, data, as_frame):
263-
# ndarray of tuples not hashable
264-
super().test_hash_pandas_object_works(data, as_frame)
265-
266258
@skip_nested
267259
def test_searchsorted(self, data_for_sorting, as_series):
268260
# Test setup fails.
@@ -273,41 +265,51 @@ def test_where_series(self, data, na_value, as_frame):
273265
# Test setup fails.
274266
super().test_where_series(data, na_value, as_frame)
275267

276-
@skip_nested
277268
@pytest.mark.parametrize("repeats", [0, 1, 2, [1, 2, 3]])
278-
def test_repeat(self, data, repeats, as_series, use_numpy):
279-
# Fails creating expected
269+
def test_repeat(self, data, repeats, as_series, use_numpy, request):
270+
if data.dtype.numpy_dtype == object and repeats != 0:
271+
mark = pytest.mark.xfail(reason="mask shapes mismatch")
272+
request.node.add_marker(mark)
280273
super().test_repeat(data, repeats, as_series, use_numpy)
281274

282275
@pytest.mark.xfail(reason="PandasArray.diff may fail on dtype")
283276
def test_diff(self, data, periods):
284277
return super().test_diff(data, periods)
285278

286-
@skip_nested
287279
@pytest.mark.parametrize("box", [pd.array, pd.Series, pd.DataFrame])
288-
def test_equals(self, data, na_value, as_series, box):
280+
def test_equals(self, data, na_value, as_series, box, request):
289281
# Fails creating with _from_sequence
282+
if box is pd.DataFrame and data.dtype.numpy_dtype == object:
283+
mark = pytest.mark.xfail(reason="AssertionError in _get_same_shape_values")
284+
request.node.add_marker(mark)
285+
290286
super().test_equals(data, na_value, as_series, box)
291287

292288

293-
@skip_nested
294289
class TestArithmetics(BaseNumPyTests, base.BaseArithmeticOpsTests):
295290
divmod_exc = None
296291
series_scalar_exc = None
297292
frame_scalar_exc = None
298293
series_array_exc = None
299294

295+
@skip_nested
296+
def test_divmod(self, data):
297+
super().test_divmod(data)
298+
299+
@skip_nested
300300
def test_divmod_series_array(self, data):
301-
s = pd.Series(data)
302-
self._check_divmod_op(s, divmod, data, exc=None)
301+
ser = pd.Series(data)
302+
self._check_divmod_op(ser, divmod, data, exc=None)
303303

304304
@pytest.mark.skip("We implement ops")
305305
def test_error(self, data, all_arithmetic_operators):
306306
pass
307307

308+
@skip_nested
308309
def test_arith_series_with_scalar(self, data, all_arithmetic_operators):
309310
super().test_arith_series_with_scalar(data, all_arithmetic_operators)
310311

312+
@skip_nested
311313
def test_arith_series_with_array(self, data, all_arithmetic_operators):
312314
super().test_arith_series_with_array(data, all_arithmetic_operators)
313315

@@ -316,14 +318,17 @@ class TestPrinting(BaseNumPyTests, base.BasePrintingTests):
316318
pass
317319

318320

319-
@skip_nested
320321
class TestNumericReduce(BaseNumPyTests, base.BaseNumericReduceTests):
321322
def check_reduce(self, s, op_name, skipna):
322323
result = getattr(s, op_name)(skipna=skipna)
323324
# avoid coercing int -> float. Just cast to the actual numpy type.
324325
expected = getattr(s.astype(s.dtype._dtype), op_name)(skipna=skipna)
325326
tm.assert_almost_equal(result, expected)
326327

328+
@pytest.mark.parametrize("skipna", [True, False])
329+
def test_reduce_series(self, data, all_boolean_reductions, skipna):
330+
super().test_reduce_series(data, all_boolean_reductions, skipna)
331+
327332

328333
@skip_nested
329334
class TestBooleanReduce(BaseNumPyTests, base.BaseBooleanReduceTests):
@@ -364,11 +369,6 @@ def test_fillna_fill_other(self, data_missing):
364369

365370

366371
class TestReshaping(BaseNumPyTests, base.BaseReshapingTests):
367-
@pytest.mark.skip("Incorrect parent test")
368-
# not actually a mixed concat, since we concat int and int.
369-
def test_concat_mixed_dtypes(self, data):
370-
super().test_concat_mixed_dtypes(data)
371-
372372
@skip_nested
373373
def test_merge(self, data, na_value):
374374
# Fails creating expected
@@ -390,22 +390,6 @@ def test_transpose_frame(self, data):
390390

391391

392392
class TestSetitem(BaseNumPyTests, base.BaseSetitemTests):
393-
@skip_nested
394-
def test_setitem_scalar_series(self, data, box_in_series):
395-
# AssertionError
396-
super().test_setitem_scalar_series(data, box_in_series)
397-
398-
@skip_nested
399-
def test_setitem_sequence(self, data, box_in_series):
400-
# ValueError: shape mismatch: value array of shape (2,1) could not
401-
# be broadcast to indexing result of shape (2,)
402-
super().test_setitem_sequence(data, box_in_series)
403-
404-
@skip_nested
405-
def test_setitem_sequence_mismatched_length_raises(self, data, as_array):
406-
# ValueError: PandasArray must be 1-dimensional.
407-
super().test_setitem_sequence_mismatched_length_raises(data, as_array)
408-
409393
@skip_nested
410394
def test_setitem_sequence_broadcasts(self, data, box_in_series):
411395
# ValueError: cannot set using a list-like indexer with a different
@@ -459,7 +443,6 @@ def test_setitem_scalar_key_sequence_raise(self, data):
459443
def test_setitem_mask(self, data, mask, box_in_series):
460444
super().test_setitem_mask(data, mask, box_in_series)
461445

462-
@skip_nested
463446
def test_setitem_mask_raises(self, data, box_in_series):
464447
super().test_setitem_mask_raises(data, box_in_series)
465448

@@ -472,7 +455,6 @@ def test_setitem_mask_raises(self, data, box_in_series):
472455
def test_setitem_integer_array(self, data, idx, box_in_series):
473456
super().test_setitem_integer_array(data, idx, box_in_series)
474457

475-
@skip_nested
476458
@pytest.mark.parametrize(
477459
"idx, box_in_series",
478460
[

0 commit comments

Comments
 (0)