Skip to content

Commit 787d6f3

Browse files
authored
TST: trim fixture to avoid xfails/skips (#39502)
1 parent 48f73d8 commit 787d6f3

File tree

5 files changed

+105
-86
lines changed

5 files changed

+105
-86
lines changed

pandas/conftest.py

+32-4
Original file line numberDiff line numberDiff line change
@@ -480,13 +480,41 @@ def index(request):
480480
index_fixture2 = index
481481

482482

483-
@pytest.fixture(params=indices_dict.keys())
483+
@pytest.fixture(
484+
params=[
485+
key for key in indices_dict if not isinstance(indices_dict[key], MultiIndex)
486+
]
487+
)
488+
def index_flat(request):
489+
"""
490+
index fixture, but excluding MultiIndex cases.
491+
"""
492+
key = request.param
493+
return indices_dict[key].copy()
494+
495+
496+
# Alias so we can test with cartesian product of index_flat
497+
index_flat2 = index_flat
498+
499+
500+
@pytest.fixture(
501+
params=[
502+
key
503+
for key in indices_dict
504+
if key not in ["int", "uint", "range", "empty", "repeats"]
505+
and not isinstance(indices_dict[key], MultiIndex)
506+
]
507+
)
484508
def index_with_missing(request):
485509
"""
486-
Fixture for indices with missing values
510+
Fixture for indices with missing values.
511+
512+
Integer-dtype and empty cases are excluded because they cannot hold missing
513+
values.
514+
515+
MultiIndex is excluded because isna() is not defined for MultiIndex.
487516
"""
488-
if request.param in ["int", "uint", "range", "empty", "repeats"]:
489-
pytest.skip("missing values not supported")
517+
490518
# GH 35538. Use deep copy to avoid illusive bug on np-dev
491519
# Azure pipeline that writes into indices_dict despite copy
492520
ind = indices_dict[request.param].copy(deep=True)

pandas/tests/indexes/common.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ def test_map(self):
630630
def test_map_dictlike(self, mapper):
631631

632632
index = self.create_index()
633-
if isinstance(index, (pd.CategoricalIndex, pd.IntervalIndex)):
633+
if isinstance(index, pd.CategoricalIndex):
634634
pytest.skip(f"skipping tests for {type(index)}")
635635

636636
identity = mapper(index.values, index)

pandas/tests/indexes/test_base.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -878,14 +878,11 @@ def test_difference_name_preservation(self, index, second_name, expected, sort):
878878
assert result.name == expected
879879

880880
def test_difference_empty_arg(self, index, sort):
881-
if isinstance(index, MultiIndex):
882-
pytest.skip("Not applicable")
883881
first = index[5:20]
884882
first.name = "name"
885883
result = first.difference([], sort)
886884

887-
assert tm.equalContents(result, first)
888-
assert result.name == first.name
885+
tm.assert_index_equal(result, first)
889886

890887
@pytest.mark.parametrize("index", ["string"], indirect=True)
891888
def test_difference_identity(self, index, sort):

pandas/tests/indexes/test_common.py

+35-49
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,9 @@ def test_droplevel(self, index):
5252
):
5353
index.droplevel(level)
5454

55-
def test_constructor_non_hashable_name(self, index):
55+
def test_constructor_non_hashable_name(self, index_flat):
5656
# GH 20527
57-
58-
if isinstance(index, MultiIndex):
59-
pytest.skip("multiindex handled in test_multi.py")
57+
index = index_flat
6058

6159
message = "Index.name must be a hashable type"
6260
renamed = [["1"]]
@@ -69,27 +67,23 @@ def test_constructor_non_hashable_name(self, index):
6967
with pytest.raises(TypeError, match=message):
7068
index.set_names(names=renamed)
7169

72-
def test_constructor_unwraps_index(self, index):
73-
if isinstance(index, pd.MultiIndex):
74-
raise pytest.skip("MultiIndex has no ._data")
75-
a = index
70+
def test_constructor_unwraps_index(self, index_flat):
71+
a = index_flat
7672
b = type(a)(a)
7773
tm.assert_equal(a._data, b._data)
7874

79-
def test_to_flat_index(self, index):
75+
def test_to_flat_index(self, index_flat):
8076
# 22866
81-
if isinstance(index, MultiIndex):
82-
pytest.skip("Separate expectation for MultiIndex")
77+
index = index_flat
8378

8479
result = index.to_flat_index()
8580
tm.assert_index_equal(result, index)
8681

87-
def test_set_name_methods(self, index):
82+
def test_set_name_methods(self, index_flat):
83+
# MultiIndex tested separately
84+
index = index_flat
8885
new_name = "This is the new name for this index"
8986

90-
# don't tests a MultiIndex here (as its tested separated)
91-
if isinstance(index, MultiIndex):
92-
pytest.skip("Skip check for MultiIndex")
9387
original_name = index.name
9488
new_ind = index.set_names([new_name])
9589
assert new_ind.name == new_name
@@ -113,11 +107,10 @@ def test_set_name_methods(self, index):
113107
assert index.name == name
114108
assert index.names == [name]
115109

116-
def test_copy_and_deepcopy(self, index):
110+
def test_copy_and_deepcopy(self, index_flat):
117111
from copy import copy, deepcopy
118112

119-
if isinstance(index, MultiIndex):
120-
pytest.skip("Skip check for MultiIndex")
113+
index = index_flat
121114

122115
for func in (copy, deepcopy):
123116
idx_copy = func(index)
@@ -127,10 +120,9 @@ def test_copy_and_deepcopy(self, index):
127120
new_copy = index.copy(deep=True, name="banana")
128121
assert new_copy.name == "banana"
129122

130-
def test_unique(self, index):
123+
def test_unique(self, index_flat):
131124
# don't test a MultiIndex here (as its tested separated)
132-
if isinstance(index, MultiIndex):
133-
pytest.skip("Skip check for MultiIndex")
125+
index = index_flat
134126

135127
# GH 17896
136128
expected = index.drop_duplicates()
@@ -149,9 +141,10 @@ def test_unique(self, index):
149141
with pytest.raises(KeyError, match=msg):
150142
index.unique(level="wrong")
151143

152-
def test_get_unique_index(self, index):
144+
def test_get_unique_index(self, index_flat):
153145
# MultiIndex tested separately
154-
if not len(index) or isinstance(index, MultiIndex):
146+
index = index_flat
147+
if not len(index):
155148
pytest.skip("Skip check for empty Index and MultiIndex")
156149

157150
idx = index[[0] * 5]
@@ -200,11 +193,12 @@ def test_get_unique_index(self, index):
200193
result = i._get_unique_index(dropna=dropna)
201194
tm.assert_index_equal(result, expected)
202195

203-
def test_searchsorted_monotonic(self, index):
196+
def test_searchsorted_monotonic(self, index_flat):
204197
# GH17271
198+
index = index_flat
205199
# not implemented for tuple searches in MultiIndex
206200
# or Intervals searches in IntervalIndex
207-
if isinstance(index, (MultiIndex, pd.IntervalIndex)):
201+
if isinstance(index, pd.IntervalIndex):
208202
pytest.skip("Skip check for MultiIndex/IntervalIndex")
209203

210204
# nothing to test if the index is empty
@@ -245,9 +239,9 @@ def test_searchsorted_monotonic(self, index):
245239
with pytest.raises(ValueError, match=msg):
246240
index._searchsorted_monotonic(value, side="left")
247241

248-
def test_drop_duplicates(self, index, keep):
249-
if isinstance(index, MultiIndex):
250-
pytest.skip("MultiIndex is tested separately")
242+
def test_drop_duplicates(self, index_flat, keep):
243+
# MultiIndex is tested separately
244+
index = index_flat
251245
if isinstance(index, RangeIndex):
252246
pytest.skip(
253247
"RangeIndex is tested in test_drop_duplicates_no_duplicates "
@@ -279,9 +273,9 @@ def test_drop_duplicates(self, index, keep):
279273
expected_dropped = holder(pd.Series(idx).drop_duplicates(keep=keep))
280274
tm.assert_index_equal(idx.drop_duplicates(keep=keep), expected_dropped)
281275

282-
def test_drop_duplicates_no_duplicates(self, index):
283-
if isinstance(index, MultiIndex):
284-
pytest.skip("MultiIndex is tested separately")
276+
def test_drop_duplicates_no_duplicates(self, index_flat):
277+
# MultiIndex is tested separately
278+
index = index_flat
285279

286280
# make unique index
287281
if isinstance(index, RangeIndex):
@@ -305,9 +299,12 @@ def test_drop_duplicates_inplace(self, index):
305299
with pytest.raises(TypeError, match=msg):
306300
index.drop_duplicates(inplace=True)
307301

308-
def test_has_duplicates(self, index):
302+
def test_has_duplicates(self, index_flat):
303+
# MultiIndex tested separately in:
304+
# tests/indexes/multi/test_unique_and_duplicates.
305+
index = index_flat
309306
holder = type(index)
310-
if not len(index) or isinstance(index, (MultiIndex, RangeIndex)):
307+
if not len(index) or isinstance(index, RangeIndex):
311308
# MultiIndex tested separately in:
312309
# tests/indexes/multi/test_unique_and_duplicates.
313310
# RangeIndex is unique by definition.
@@ -363,29 +360,18 @@ def test_asi8_deprecation(self, index):
363360

364361

365362
@pytest.mark.parametrize("na_position", [None, "middle"])
366-
def test_sort_values_invalid_na_position(request, index_with_missing, na_position):
367-
if isinstance(index_with_missing, MultiIndex):
368-
request.node.add_marker(
369-
pytest.mark.xfail(
370-
reason="missing value sorting order not defined for index type"
371-
)
372-
)
363+
def test_sort_values_invalid_na_position(index_with_missing, na_position):
373364

374-
if na_position not in ["first", "last"]:
375-
with pytest.raises(ValueError, match=f"invalid na_position: {na_position}"):
376-
index_with_missing.sort_values(na_position=na_position)
365+
with pytest.raises(ValueError, match=f"invalid na_position: {na_position}"):
366+
index_with_missing.sort_values(na_position=na_position)
377367

378368

379369
@pytest.mark.parametrize("na_position", ["first", "last"])
380-
def test_sort_values_with_missing(request, index_with_missing, na_position):
370+
def test_sort_values_with_missing(index_with_missing, na_position):
381371
# GH 35584. Test that sort_values works with missing values,
382372
# sort non-missing and place missing according to na_position
383373

384-
if isinstance(index_with_missing, MultiIndex):
385-
request.node.add_marker(
386-
pytest.mark.xfail(reason="missing value sorting order not implemented")
387-
)
388-
elif isinstance(index_with_missing, CategoricalIndex):
374+
if isinstance(index_with_missing, CategoricalIndex):
389375
pytest.skip("missing value sorting order not well-defined")
390376

391377
missing_count = np.sum(index_with_missing.isna())

pandas/tests/indexes/test_setops.py

+36-28
Original file line numberDiff line numberDiff line change
@@ -38,33 +38,39 @@ def test_union_same_types(index):
3838
assert idx1.union(idx2).dtype == idx1.dtype
3939

4040

41-
def test_union_different_types(request, index, index_fixture2):
41+
def test_union_different_types(index_flat, index_flat2):
4242
# This test only considers combinations of indices
4343
# GH 23525
44-
idx1, idx2 = index, index_fixture2
45-
type_pair = tuple(sorted([type(idx1), type(idx2)], key=lambda x: str(x)))
46-
if type_pair in COMPATIBLE_INCONSISTENT_PAIRS:
47-
request.node.add_marker(
48-
pytest.mark.xfail(reason="This test only considers non compatible indexes.")
49-
)
50-
51-
if any(isinstance(idx, pd.MultiIndex) for idx in (idx1, idx2)):
52-
pytest.skip("This test doesn't consider multiindixes.")
44+
idx1 = index_flat
45+
idx2 = index_flat2
5346

54-
if is_dtype_equal(idx1.dtype, idx2.dtype):
55-
pytest.skip("This test only considers non matching dtypes.")
56-
57-
# A union with a CategoricalIndex (even as dtype('O')) and a
58-
# non-CategoricalIndex can only be made if both indices are monotonic.
59-
# This is true before this PR as well.
47+
type_pair = tuple(sorted([type(idx1), type(idx2)], key=lambda x: str(x)))
6048

6149
# Union with a non-unique, non-monotonic index raises error
6250
# This applies to the boolean index
6351
idx1 = idx1.sort_values()
6452
idx2 = idx2.sort_values()
6553

66-
assert idx1.union(idx2).dtype == np.dtype("O")
67-
assert idx2.union(idx1).dtype == np.dtype("O")
54+
res1 = idx1.union(idx2)
55+
res2 = idx2.union(idx1)
56+
57+
if is_dtype_equal(idx1.dtype, idx2.dtype):
58+
assert res1.dtype == idx1.dtype
59+
assert res2.dtype == idx1.dtype
60+
61+
elif type_pair not in COMPATIBLE_INCONSISTENT_PAIRS:
62+
# A union with a CategoricalIndex (even as dtype('O')) and a
63+
# non-CategoricalIndex can only be made if both indices are monotonic.
64+
# This is true before this PR as well.
65+
assert res1.dtype == np.dtype("O")
66+
assert res2.dtype == np.dtype("O")
67+
68+
elif idx1.dtype.kind in ["f", "i", "u"] and idx2.dtype.kind in ["f", "i", "u"]:
69+
assert res1.dtype == np.dtype("f8")
70+
assert res2.dtype == np.dtype("f8")
71+
72+
else:
73+
raise NotImplementedError
6874

6975

7076
@pytest.mark.parametrize("idx_fact1,idx_fact2", COMPATIBLE_INCONSISTENT_PAIRS.values())
@@ -275,12 +281,12 @@ def test_symmetric_difference(self, index):
275281
(None, None, None),
276282
],
277283
)
278-
def test_corner_union(self, index, fname, sname, expected_name):
284+
def test_corner_union(self, index_flat, fname, sname, expected_name):
279285
# GH#9943, GH#9862
280286
# Test unions with various name combinations
281287
# Do not test MultiIndex or repeats
282-
283-
if isinstance(index, MultiIndex) or not index.is_unique:
288+
index = index_flat
289+
if not index.is_unique:
284290
pytest.skip("Not for MultiIndex or repeated indices")
285291

286292
# Test copy.union(copy)
@@ -321,8 +327,9 @@ def test_corner_union(self, index, fname, sname, expected_name):
321327
(None, None, None),
322328
],
323329
)
324-
def test_union_unequal(self, index, fname, sname, expected_name):
325-
if isinstance(index, MultiIndex) or not index.is_unique:
330+
def test_union_unequal(self, index_flat, fname, sname, expected_name):
331+
index = index_flat
332+
if not index.is_unique:
326333
pytest.skip("Not for MultiIndex or repeated indices")
327334

328335
# test copy.union(subset) - need sort for unicode and string
@@ -342,11 +349,11 @@ def test_union_unequal(self, index, fname, sname, expected_name):
342349
(None, None, None),
343350
],
344351
)
345-
def test_corner_intersect(self, index, fname, sname, expected_name):
352+
def test_corner_intersect(self, index_flat, fname, sname, expected_name):
346353
# GH#35847
347354
# Test intersections with various name combinations
348-
349-
if isinstance(index, MultiIndex) or not index.is_unique:
355+
index = index_flat
356+
if not index.is_unique:
350357
pytest.skip("Not for MultiIndex or repeated indices")
351358

352359
# Test copy.intersection(copy)
@@ -387,8 +394,9 @@ def test_corner_intersect(self, index, fname, sname, expected_name):
387394
(None, None, None),
388395
],
389396
)
390-
def test_intersect_unequal(self, index, fname, sname, expected_name):
391-
if isinstance(index, MultiIndex) or not index.is_unique:
397+
def test_intersect_unequal(self, index_flat, fname, sname, expected_name):
398+
index = index_flat
399+
if not index.is_unique:
392400
pytest.skip("Not for MultiIndex or repeated indices")
393401

394402
# test copy.intersection(subset) - need sort for unicode and string

0 commit comments

Comments
 (0)