Skip to content

Commit 37ae5c4

Browse files
authored
TST: Simplify and clarify test skipping (#56027)
* TST: Simplify and clarify test skipping * Typo * Update pandas/tests/arithmetic/test_datetime64.py * Don't skip because of duplicates
1 parent fd55cbe commit 37ae5c4

28 files changed

+94
-180
lines changed

pandas/tests/arithmetic/test_datetime64.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ def test_dti_cmp_datetimelike(self, other, tz_naive_fixture):
414414
dti = date_range("2016-01-01", periods=2, tz=tz)
415415
if tz is not None:
416416
if isinstance(other, np.datetime64):
417-
pytest.skip("no tzaware version available")
417+
pytest.skip(f"{type(other).__name__} is not tz aware")
418418
other = localize_pydatetime(other, dti.tzinfo)
419419

420420
result = dti == other

pandas/tests/arithmetic/test_numeric.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ def test_divmod_zero(self, zero, numeric_idx):
384384
def test_div_negative_zero(self, zero, numeric_idx, op):
385385
# Check that -1 / -0.0 returns np.inf, not -np.inf
386386
if numeric_idx.dtype == np.uint64:
387-
pytest.skip(f"Not relevant for {numeric_idx.dtype}")
387+
pytest.skip(f"Div by negative 0 not relevant for {numeric_idx.dtype}")
388388
idx = numeric_idx - 3
389389

390390
expected = Index([-np.inf, -np.inf, -np.inf, np.nan, np.inf], dtype=np.float64)

pandas/tests/computation/test_eval.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
reason=f"numexpr enabled->{USE_NUMEXPR}, "
6464
f"installed->{NUMEXPR_INSTALLED}",
6565
),
66-
td.skip_if_no_ne,
66+
td.skip_if_no("numexpr"),
6767
],
6868
)
6969
for engine in ENGINES
@@ -1687,14 +1687,14 @@ def test_empty_globals(self, engine, parser):
16871687
pd.eval(e, engine=engine, parser=parser, global_dict={})
16881688

16891689

1690-
@td.skip_if_no_ne
1690+
@td.skip_if_no("numexpr")
16911691
def test_invalid_engine():
16921692
msg = "Invalid engine 'asdf' passed"
16931693
with pytest.raises(KeyError, match=msg):
16941694
pd.eval("x + y", local_dict={"x": 1, "y": 2}, engine="asdf")
16951695

16961696

1697-
@td.skip_if_no_ne
1697+
@td.skip_if_no("numexpr")
16981698
@pytest.mark.parametrize(
16991699
("use_numexpr", "expected"),
17001700
(
@@ -1711,7 +1711,7 @@ def test_numexpr_option_respected(use_numexpr, expected):
17111711
assert result == expected
17121712

17131713

1714-
@td.skip_if_no_ne
1714+
@td.skip_if_no("numexpr")
17151715
def test_numexpr_option_incompatible_op():
17161716
# GH 32556
17171717
with pd.option_context("compute.use_numexpr", False):
@@ -1723,7 +1723,7 @@ def test_numexpr_option_incompatible_op():
17231723
tm.assert_frame_equal(result, expected)
17241724

17251725

1726-
@td.skip_if_no_ne
1726+
@td.skip_if_no("numexpr")
17271727
def test_invalid_parser():
17281728
msg = "Invalid parser 'asdf' passed"
17291729
with pytest.raises(KeyError, match=msg):

pandas/tests/dtypes/test_common.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ def test_is_object():
196196

197197

198198
@pytest.mark.parametrize(
199-
"check_scipy", [False, pytest.param(True, marks=td.skip_if_no_scipy)]
199+
"check_scipy", [False, pytest.param(True, marks=td.skip_if_no("scipy"))]
200200
)
201201
def test_is_sparse(check_scipy):
202202
msg = "is_sparse is deprecated"
@@ -632,7 +632,7 @@ def test_is_bool_dtype_numpy_error():
632632

633633

634634
@pytest.mark.parametrize(
635-
"check_scipy", [False, pytest.param(True, marks=td.skip_if_no_scipy)]
635+
"check_scipy", [False, pytest.param(True, marks=td.skip_if_no("scipy"))]
636636
)
637637
def test_is_extension_array_dtype(check_scipy):
638638
assert not com.is_extension_array_dtype([1, 2, 3])

pandas/tests/extension/base/dim2.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def skip_if_doesnt_support_2d(self, dtype, request):
2929
test_func = node._obj
3030
if test_func.__qualname__.startswith("Dim2CompatTests"):
3131
# TODO: is there a less hacky way of checking this?
32-
pytest.skip("Test is only for EAs that support 2D.")
32+
pytest.skip(f"{dtype} does not support 2D.")
3333

3434
def test_transpose(self, data):
3535
arr2d = data.repeat(2).reshape(-1, 2)

pandas/tests/extension/base/interface.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def test_copy(self, data):
103103
result = data.copy()
104104

105105
if data.dtype._is_immutable:
106-
pytest.skip("test_copy assumes mutability")
106+
pytest.skip(f"test_copy assumes mutability and {data.dtype} is immutable")
107107

108108
data[1] = data[0]
109109
assert result[1] != result[0]
@@ -118,7 +118,7 @@ def test_view(self, data):
118118
assert type(result) == type(data)
119119

120120
if data.dtype._is_immutable:
121-
pytest.skip("test_view assumes mutability")
121+
pytest.skip(f"test_view assumes mutability and {data.dtype} is immutable")
122122

123123
result[1] = result[0]
124124
assert data[1] == data[0]

pandas/tests/extension/base/reduce.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def test_reduce_frame(self, data, all_numeric_reductions, skipna):
120120
op_name = all_numeric_reductions
121121
ser = pd.Series(data)
122122
if not is_numeric_dtype(ser.dtype):
123-
pytest.skip("not numeric dtype")
123+
pytest.skip(f"{ser.dtype} is not numeric dtype")
124124

125125
if op_name in ["count", "kurt", "sem"]:
126126
pytest.skip(f"{op_name} not an array method")

pandas/tests/extension/base/reshaping.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ def test_ravel(self, data):
343343
assert type(result) == type(data)
344344

345345
if data.dtype._is_immutable:
346-
pytest.skip("test_ravel assumes mutability")
346+
pytest.skip(f"test_ravel assumes mutability and {data.dtype} is immutable")
347347

348348
# Check that we have a view, not a copy
349349
result[0] = result[1]
@@ -360,7 +360,9 @@ def test_transpose(self, data):
360360
assert result.shape == data.shape[::-1]
361361

362362
if data.dtype._is_immutable:
363-
pytest.skip("test_transpose assumes mutability")
363+
pytest.skip(
364+
f"test_transpose assumes mutability and {data.dtype} is immutable"
365+
)
364366

365367
# Check that we have a view, not a copy
366368
result[0] = result[1]

pandas/tests/extension/base/setitem.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def skip_if_immutable(self, dtype, request):
4343
# This fixture is auto-used, but we want to not-skip
4444
# test_is_immutable.
4545
return
46-
pytest.skip("__setitem__ test not applicable with immutable dtype")
46+
pytest.skip(f"__setitem__ test not applicable with immutable dtype {dtype}")
4747

4848
def test_is_immutable(self, data):
4949
if data.dtype._is_immutable:

pandas/tests/extension/conftest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def data_for_twos(dtype):
3737
if not (dtype._is_numeric or dtype.kind == "m"):
3838
# Object-dtypes may want to allow this, but for the most part
3939
# only numeric and timedelta-like dtypes will need to implement this.
40-
pytest.skip("Not a numeric dtype")
40+
pytest.skip(f"{dtype} is not a numeric dtype")
4141

4242
raise NotImplementedError
4343

pandas/tests/extension/test_interval.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def data_missing():
5656

5757
@pytest.fixture
5858
def data_for_twos():
59-
pytest.skip("Not a numeric dtype")
59+
pytest.skip("Interval is not a numeric dtype")
6060

6161

6262
@pytest.fixture

pandas/tests/extension/test_numpy.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ def data_for_grouping(allow_in_pandas, dtype):
151151
@pytest.fixture
152152
def data_for_twos(dtype):
153153
if dtype.kind == "O":
154-
pytest.skip("Not a numeric dtype")
154+
pytest.skip(f"{dtype} is not a numeric dtype")
155155
arr = np.ones(100) * 2
156156
return NumpyExtensionArray._from_sequence(arr, dtype=dtype)
157157

@@ -323,7 +323,7 @@ def check_reduce(self, ser: pd.Series, op_name: str, skipna: bool):
323323
expected = exp_op(skipna=skipna)
324324
tm.assert_almost_equal(result, expected)
325325

326-
@pytest.mark.skip("tests not written yet")
326+
@pytest.mark.skip("TODO: tests not written yet")
327327
@pytest.mark.parametrize("skipna", [True, False])
328328
def test_reduce_frame(self, data, all_numeric_reductions, skipna):
329329
pass

pandas/tests/extension/test_string.py

+20-21
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,21 @@
2626
from pandas.tests.extension import base
2727

2828

29-
def split_array(arr):
30-
if arr.dtype.storage != "pyarrow":
31-
pytest.skip("only applicable for pyarrow chunked array n/a")
32-
33-
def _split_array(arr):
34-
import pyarrow as pa
35-
36-
arrow_array = arr._pa_array
37-
split = len(arrow_array) // 2
38-
arrow_array = pa.chunked_array(
39-
[*arrow_array[:split].chunks, *arrow_array[split:].chunks]
40-
)
41-
assert arrow_array.num_chunks == 2
42-
return type(arr)(arrow_array)
43-
44-
return _split_array(arr)
29+
def maybe_split_array(arr, chunked):
30+
if not chunked:
31+
return arr
32+
elif arr.dtype.storage != "pyarrow":
33+
return arr
34+
35+
pa = pytest.importorskip("pyarrow")
36+
37+
arrow_array = arr._pa_array
38+
split = len(arrow_array) // 2
39+
arrow_array = pa.chunked_array(
40+
[*arrow_array[:split].chunks, *arrow_array[split:].chunks]
41+
)
42+
assert arrow_array.num_chunks == 2
43+
return type(arr)(arrow_array)
4544

4645

4746
@pytest.fixture(params=[True, False])
@@ -61,34 +60,34 @@ def data(dtype, chunked):
6160
strings = np.random.default_rng(2).choice(list(string.ascii_letters), size=100)
6261

6362
arr = dtype.construct_array_type()._from_sequence(strings)
64-
return split_array(arr) if chunked else arr
63+
return maybe_split_array(arr, chunked)
6564

6665

6766
@pytest.fixture
6867
def data_missing(dtype, chunked):
6968
"""Length 2 array with [NA, Valid]"""
7069
arr = dtype.construct_array_type()._from_sequence([pd.NA, "A"])
71-
return split_array(arr) if chunked else arr
70+
return maybe_split_array(arr, chunked)
7271

7372

7473
@pytest.fixture
7574
def data_for_sorting(dtype, chunked):
7675
arr = dtype.construct_array_type()._from_sequence(["B", "C", "A"])
77-
return split_array(arr) if chunked else arr
76+
return maybe_split_array(arr, chunked)
7877

7978

8079
@pytest.fixture
8180
def data_missing_for_sorting(dtype, chunked):
8281
arr = dtype.construct_array_type()._from_sequence(["B", pd.NA, "A"])
83-
return split_array(arr) if chunked else arr
82+
return maybe_split_array(arr, chunked)
8483

8584

8685
@pytest.fixture
8786
def data_for_grouping(dtype, chunked):
8887
arr = dtype.construct_array_type()._from_sequence(
8988
["B", "B", pd.NA, pd.NA, "A", "A", "B", "C"]
9089
)
91-
return split_array(arr) if chunked else arr
90+
return maybe_split_array(arr, chunked)
9291

9392

9493
class TestDtype(base.BaseDtypeTests):

pandas/tests/frame/methods/test_interpolate.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ def test_rowwise_alt(self):
322322
# TODO: assert something?
323323

324324
@pytest.mark.parametrize(
325-
"check_scipy", [False, pytest.param(True, marks=td.skip_if_no_scipy)]
325+
"check_scipy", [False, pytest.param(True, marks=td.skip_if_no("scipy"))]
326326
)
327327
def test_interp_leading_nans(self, check_scipy):
328328
df = DataFrame(

pandas/tests/frame/test_query_eval.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,16 @@ def parser(request):
2727

2828

2929
@pytest.fixture(
30-
params=["python", pytest.param("numexpr", marks=td.skip_if_no_ne)], ids=lambda x: x
30+
params=["python", pytest.param("numexpr", marks=td.skip_if_no("numexpr"))],
31+
ids=lambda x: x,
3132
)
3233
def engine(request):
3334
return request.param
3435

3536

3637
def skip_if_no_pandas_parser(parser):
3738
if parser != "pandas":
38-
pytest.skip(f"cannot evaluate with parser {repr(parser)}")
39+
pytest.skip(f"cannot evaluate with parser={parser}")
3940

4041

4142
class TestCompat:
@@ -387,7 +388,7 @@ def to_series(mi, level):
387388
raise AssertionError("object must be a Series or Index")
388389

389390

390-
@td.skip_if_no_ne
391+
@td.skip_if_no("numexpr")
391392
class TestDataFrameQueryNumExprPandas:
392393
@pytest.fixture
393394
def engine(self):
@@ -765,7 +766,7 @@ def test_method_calls_in_query(self, engine, parser):
765766
tm.assert_frame_equal(result, expected)
766767

767768

768-
@td.skip_if_no_ne
769+
@td.skip_if_no("numexpr")
769770
class TestDataFrameQueryNumExprPython(TestDataFrameQueryNumExprPandas):
770771
@pytest.fixture
771772
def engine(self):

pandas/tests/frame/test_reductions.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ class TestDataFrameAnalytics:
165165
"var",
166166
"std",
167167
"sem",
168-
pytest.param("skew", marks=td.skip_if_no_scipy),
169-
pytest.param("kurt", marks=td.skip_if_no_scipy),
168+
pytest.param("skew", marks=td.skip_if_no("scipy")),
169+
pytest.param("kurt", marks=td.skip_if_no("scipy")),
170170
],
171171
)
172172
def test_stat_op_api_float_string_frame(self, float_string_frame, axis, opname):
@@ -219,8 +219,8 @@ def test_stat_op_api_float_string_frame(self, float_string_frame, axis, opname):
219219
"var",
220220
"std",
221221
"sem",
222-
pytest.param("skew", marks=td.skip_if_no_scipy),
223-
pytest.param("kurt", marks=td.skip_if_no_scipy),
222+
pytest.param("skew", marks=td.skip_if_no("scipy")),
223+
pytest.param("kurt", marks=td.skip_if_no("scipy")),
224224
],
225225
)
226226
def test_stat_op_api_float_frame(self, float_frame, axis, opname):

pandas/tests/groupby/test_reductions.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ def scipy_sem(*args, **kwargs):
933933
("first", lambda x: x.iloc[0]),
934934
("last", lambda x: x.iloc[-1]),
935935
("count", np.size),
936-
pytest.param("sem", scipy_sem, marks=td.skip_if_no_scipy),
936+
pytest.param("sem", scipy_sem, marks=td.skip_if_no("scipy")),
937937
],
938938
)
939939
def test_ops_general(op, targop):

pandas/tests/indexes/test_setops.py

+12-8
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,9 @@ def test_corner_union(self, index_flat, fname, sname, expected_name):
320320
# Test unions with various name combinations
321321
# Do not test MultiIndex or repeats
322322
if not index_flat.is_unique:
323-
pytest.skip("Randomly generated index_flat was not unique.")
324-
index = index_flat
323+
index = index_flat.unique()
324+
else:
325+
index = index_flat
325326

326327
# Test copy.union(copy)
327328
first = index.copy().set_names(fname)
@@ -363,8 +364,9 @@ def test_corner_union(self, index_flat, fname, sname, expected_name):
363364
)
364365
def test_union_unequal(self, index_flat, fname, sname, expected_name):
365366
if not index_flat.is_unique:
366-
pytest.skip("Randomly generated index_flat was not unique.")
367-
index = index_flat
367+
index = index_flat.unique()
368+
else:
369+
index = index_flat
368370

369371
# test copy.union(subset) - need sort for unicode and string
370372
first = index.copy().set_names(fname)
@@ -387,8 +389,9 @@ def test_corner_intersect(self, index_flat, fname, sname, expected_name):
387389
# GH#35847
388390
# Test intersections with various name combinations
389391
if not index_flat.is_unique:
390-
pytest.skip("Randomly generated index_flat was not unique.")
391-
index = index_flat
392+
index = index_flat.unique()
393+
else:
394+
index = index_flat
392395

393396
# Test copy.intersection(copy)
394397
first = index.copy().set_names(fname)
@@ -430,8 +433,9 @@ def test_corner_intersect(self, index_flat, fname, sname, expected_name):
430433
)
431434
def test_intersect_unequal(self, index_flat, fname, sname, expected_name):
432435
if not index_flat.is_unique:
433-
pytest.skip("Randomly generated index_flat was not unique.")
434-
index = index_flat
436+
index = index_flat.unique()
437+
else:
438+
index = index_flat
435439

436440
# test copy.intersection(subset) - need sort for unicode and string
437441
first = index.copy().set_names(fname)

0 commit comments

Comments
 (0)