Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TST: Simplify and clarify test skipping #56027

Merged
merged 6 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pandas/tests/arithmetic/test_datetime64.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ def test_dti_cmp_datetimelike(self, other, tz_naive_fixture):
dti = date_range("2016-01-01", periods=2, tz=tz)
if tz is not None:
if isinstance(other, np.datetime64):
pytest.skip("no tzaware version available")
pytest.skip(f"{type(other.__name__)} is not tz aware")
mroeschke marked this conversation as resolved.
Show resolved Hide resolved
other = localize_pydatetime(other, dti.tzinfo)

result = dti == other
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/arithmetic/test_numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ def test_divmod_zero(self, zero, numeric_idx):
def test_div_negative_zero(self, zero, numeric_idx, op):
# Check that -1 / -0.0 returns np.inf, not -np.inf
if numeric_idx.dtype == np.uint64:
pytest.skip(f"Not relevant for {numeric_idx.dtype}")
pytest.skip(f"Div by negative 0 not relevant for {numeric_idx.dtype}")
idx = numeric_idx - 3

expected = Index([-np.inf, -np.inf, -np.inf, np.nan, np.inf], dtype=np.float64)
Expand Down
10 changes: 5 additions & 5 deletions pandas/tests/computation/test_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
reason=f"numexpr enabled->{USE_NUMEXPR}, "
f"installed->{NUMEXPR_INSTALLED}",
),
td.skip_if_no_ne,
td.skip_if_no("numexpr"),
],
)
for engine in ENGINES
Expand Down Expand Up @@ -1687,14 +1687,14 @@ def test_empty_globals(self, engine, parser):
pd.eval(e, engine=engine, parser=parser, global_dict={})


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


@td.skip_if_no_ne
@td.skip_if_no("numexpr")
@pytest.mark.parametrize(
("use_numexpr", "expected"),
(
Expand All @@ -1711,7 +1711,7 @@ def test_numexpr_option_respected(use_numexpr, expected):
assert result == expected


@td.skip_if_no_ne
@td.skip_if_no("numexpr")
def test_numexpr_option_incompatible_op():
# GH 32556
with pd.option_context("compute.use_numexpr", False):
Expand All @@ -1723,7 +1723,7 @@ def test_numexpr_option_incompatible_op():
tm.assert_frame_equal(result, expected)


@td.skip_if_no_ne
@td.skip_if_no("numexpr")
def test_invalid_parser():
msg = "Invalid parser 'asdf' passed"
with pytest.raises(KeyError, match=msg):
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/dtypes/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def test_is_object():


@pytest.mark.parametrize(
"check_scipy", [False, pytest.param(True, marks=td.skip_if_no_scipy)]
"check_scipy", [False, pytest.param(True, marks=td.skip_if_no("scipy"))]
)
def test_is_sparse(check_scipy):
msg = "is_sparse is deprecated"
Expand Down Expand Up @@ -632,7 +632,7 @@ def test_is_bool_dtype_numpy_error():


@pytest.mark.parametrize(
"check_scipy", [False, pytest.param(True, marks=td.skip_if_no_scipy)]
"check_scipy", [False, pytest.param(True, marks=td.skip_if_no("scipy"))]
)
def test_is_extension_array_dtype(check_scipy):
assert not com.is_extension_array_dtype([1, 2, 3])
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/extension/base/dim2.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def skip_if_doesnt_support_2d(self, dtype, request):
test_func = node._obj
if test_func.__qualname__.startswith("Dim2CompatTests"):
# TODO: is there a less hacky way of checking this?
pytest.skip("Test is only for EAs that support 2D.")
pytest.skip(f"{dtype} does not support 2D.")

def test_transpose(self, data):
arr2d = data.repeat(2).reshape(-1, 2)
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/extension/base/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def test_copy(self, data):
result = data.copy()

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

data[1] = data[0]
assert result[1] != result[0]
Expand All @@ -118,7 +118,7 @@ def test_view(self, data):
assert type(result) == type(data)

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

result[1] = result[0]
assert data[1] == data[0]
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/extension/base/reduce.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def test_reduce_frame(self, data, all_numeric_reductions, skipna):
op_name = all_numeric_reductions
ser = pd.Series(data)
if not is_numeric_dtype(ser.dtype):
pytest.skip("not numeric dtype")
pytest.skip(f"{ser.dtype} is not numeric dtype")

if op_name in ["count", "kurt", "sem"]:
pytest.skip(f"{op_name} not an array method")
Expand Down
6 changes: 4 additions & 2 deletions pandas/tests/extension/base/reshaping.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ def test_ravel(self, data):
assert type(result) == type(data)

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

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

if data.dtype._is_immutable:
pytest.skip("test_transpose assumes mutability")
pytest.skip(
f"test_transpose assumes mutability and {data.dtype} is immutable"
)

# Check that we have a view, not a copy
result[0] = result[1]
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/extension/base/setitem.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def skip_if_immutable(self, dtype, request):
# This fixture is auto-used, but we want to not-skip
# test_is_immutable.
return
pytest.skip("__setitem__ test not applicable with immutable dtype")
pytest.skip(f"__setitem__ test not applicable with immutable dtype {dtype}")

def test_is_immutable(self, data):
if data.dtype._is_immutable:
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/extension/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def data_for_twos(dtype):
if not (dtype._is_numeric or dtype.kind == "m"):
# Object-dtypes may want to allow this, but for the most part
# only numeric and timedelta-like dtypes will need to implement this.
pytest.skip("Not a numeric dtype")
pytest.skip(f"{dtype} is not a numeric dtype")

raise NotImplementedError

Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/extension/test_interval.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def data_missing():

@pytest.fixture
def data_for_twos():
pytest.skip("Not a numeric dtype")
pytest.skip("Interval is not a numeric dtype")


@pytest.fixture
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/extension/test_numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def data_for_grouping(allow_in_pandas, dtype):
@pytest.fixture
def data_for_twos(dtype):
if dtype.kind == "O":
pytest.skip("Not a numeric dtype")
pytest.skip(f"{dtype} is not a numeric dtype")
arr = np.ones(100) * 2
return NumpyExtensionArray._from_sequence(arr, dtype=dtype)

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

@pytest.mark.skip("tests not written yet")
@pytest.mark.skip("TODO: tests not written yet")
@pytest.mark.parametrize("skipna", [True, False])
def test_reduce_frame(self, data, all_numeric_reductions, skipna):
pass
Expand Down
41 changes: 20 additions & 21 deletions pandas/tests/extension/test_string.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,21 @@
from pandas.tests.extension import base


def split_array(arr):
if arr.dtype.storage != "pyarrow":
pytest.skip("only applicable for pyarrow chunked array n/a")

def _split_array(arr):
import pyarrow as pa

arrow_array = arr._pa_array
split = len(arrow_array) // 2
arrow_array = pa.chunked_array(
[*arrow_array[:split].chunks, *arrow_array[split:].chunks]
)
assert arrow_array.num_chunks == 2
return type(arr)(arrow_array)

return _split_array(arr)
def maybe_split_array(arr, chunked):
if not chunked:
return arr
elif arr.dtype.storage != "pyarrow":
return arr

pa = pytest.importorskip("pyarrow")

arrow_array = arr._pa_array
split = len(arrow_array) // 2
arrow_array = pa.chunked_array(
[*arrow_array[:split].chunks, *arrow_array[split:].chunks]
)
assert arrow_array.num_chunks == 2
return type(arr)(arrow_array)


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

arr = dtype.construct_array_type()._from_sequence(strings)
return split_array(arr) if chunked else arr
return maybe_split_array(arr, chunked)


@pytest.fixture
def data_missing(dtype, chunked):
"""Length 2 array with [NA, Valid]"""
arr = dtype.construct_array_type()._from_sequence([pd.NA, "A"])
return split_array(arr) if chunked else arr
return maybe_split_array(arr, chunked)


@pytest.fixture
def data_for_sorting(dtype, chunked):
arr = dtype.construct_array_type()._from_sequence(["B", "C", "A"])
return split_array(arr) if chunked else arr
return maybe_split_array(arr, chunked)


@pytest.fixture
def data_missing_for_sorting(dtype, chunked):
arr = dtype.construct_array_type()._from_sequence(["B", pd.NA, "A"])
return split_array(arr) if chunked else arr
return maybe_split_array(arr, chunked)


@pytest.fixture
def data_for_grouping(dtype, chunked):
arr = dtype.construct_array_type()._from_sequence(
["B", "B", pd.NA, pd.NA, "A", "A", "B", "C"]
)
return split_array(arr) if chunked else arr
return maybe_split_array(arr, chunked)


class TestDtype(base.BaseDtypeTests):
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/frame/methods/test_interpolate.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ def test_rowwise_alt(self):
# TODO: assert something?

@pytest.mark.parametrize(
"check_scipy", [False, pytest.param(True, marks=td.skip_if_no_scipy)]
"check_scipy", [False, pytest.param(True, marks=td.skip_if_no("scipy"))]
)
def test_interp_leading_nans(self, check_scipy):
df = DataFrame(
Expand Down
9 changes: 5 additions & 4 deletions pandas/tests/frame/test_query_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@ def parser(request):


@pytest.fixture(
params=["python", pytest.param("numexpr", marks=td.skip_if_no_ne)], ids=lambda x: x
params=["python", pytest.param("numexpr", marks=td.skip_if_no("numexpr"))],
ids=lambda x: x,
)
def engine(request):
return request.param


def skip_if_no_pandas_parser(parser):
if parser != "pandas":
pytest.skip(f"cannot evaluate with parser {repr(parser)}")
pytest.skip(f"cannot evaluate with parser={parser}")


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


@td.skip_if_no_ne
@td.skip_if_no("numexpr")
class TestDataFrameQueryNumExprPandas:
@pytest.fixture
def engine(self):
Expand Down Expand Up @@ -765,7 +766,7 @@ def test_method_calls_in_query(self, engine, parser):
tm.assert_frame_equal(result, expected)


@td.skip_if_no_ne
@td.skip_if_no("numexpr")
class TestDataFrameQueryNumExprPython(TestDataFrameQueryNumExprPandas):
@pytest.fixture
def engine(self):
Expand Down
8 changes: 4 additions & 4 deletions pandas/tests/frame/test_reductions.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ class TestDataFrameAnalytics:
"var",
"std",
"sem",
pytest.param("skew", marks=td.skip_if_no_scipy),
pytest.param("kurt", marks=td.skip_if_no_scipy),
pytest.param("skew", marks=td.skip_if_no("scipy")),
pytest.param("kurt", marks=td.skip_if_no("scipy")),
],
)
def test_stat_op_api_float_string_frame(self, float_string_frame, axis, opname):
Expand Down Expand Up @@ -219,8 +219,8 @@ def test_stat_op_api_float_string_frame(self, float_string_frame, axis, opname):
"var",
"std",
"sem",
pytest.param("skew", marks=td.skip_if_no_scipy),
pytest.param("kurt", marks=td.skip_if_no_scipy),
pytest.param("skew", marks=td.skip_if_no("scipy")),
pytest.param("kurt", marks=td.skip_if_no("scipy")),
],
)
def test_stat_op_api_float_frame(self, float_frame, axis, opname):
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/groupby/test_reductions.py
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,7 @@ def scipy_sem(*args, **kwargs):
("first", lambda x: x.iloc[0]),
("last", lambda x: x.iloc[-1]),
("count", np.size),
pytest.param("sem", scipy_sem, marks=td.skip_if_no_scipy),
pytest.param("sem", scipy_sem, marks=td.skip_if_no("scipy")),
],
)
def test_ops_general(op, targop):
Expand Down
5 changes: 3 additions & 2 deletions pandas/tests/indexes/test_setops.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,9 @@ def test_corner_union(self, index_flat, fname, sname, expected_name):
# Test unions with various name combinations
# Do not test MultiIndex or repeats
if not index_flat.is_unique:
pytest.skip("Randomly generated index_flat was not unique.")
index = index_flat
index = index_flat.unique()
else:
index = index_flat

# Test copy.union(copy)
first = index.copy().set_names(fname)
Expand Down
5 changes: 4 additions & 1 deletion pandas/tests/io/excel/test_writers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import pytest

from pandas.compat._constants import PY310
from pandas.compat._optional import import_optional_dependency
import pandas.util._test_decorators as td

import pandas as pd
Expand Down Expand Up @@ -1309,7 +1310,9 @@ class TestExcelWriterEngineTests:
def test_ExcelWriter_dispatch(self, klass, ext):
with tm.ensure_clean(ext) as path:
with ExcelWriter(path) as writer:
if ext == ".xlsx" and td.safe_import("xlsxwriter"):
if ext == ".xlsx" and bool(
import_optional_dependency("xlsxwriter", errors="ignore")
):
# xlsxwriter has preference over openpyxl if both installed
assert isinstance(writer, _XlsxWriter)
else:
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/plotting/frame/test_frame_legend.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def test_legend_name(self):
"line",
"bar",
"barh",
pytest.param("kde", marks=td.skip_if_no_scipy),
pytest.param("kde", marks=td.skip_if_no("scipy")),
"area",
"hist",
],
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/plotting/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def test_setting_backend_without_plot_raises(monkeypatch):
assert pandas.options.plotting.backend == "matplotlib"


@td.skip_if_mpl
@td.skip_if_installed("matplotlib")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any perf impact of evaluating these once vs in a bunch of places?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very slight. e.g. when running test_eval.py with skip_if_no_ne replaced locally I'm getting a runtime of 26.86s on this PR vs 26.69s on main. IMO I think this timing difference is OK given the cleanup

def test_no_matplotlib_ok():
msg = (
'matplotlib is required for plotting when the default backend "matplotlib" is '
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/plotting/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
cm = pytest.importorskip("matplotlib.cm")


@td.skip_if_mpl
@td.skip_if_installed("matplotlib")
def test_import_error_message():
# GH-19810
df = DataFrame({"A": [1, 2]})
Expand Down
Loading
Loading