diff --git a/ci/requirements/environment.yaml b/ci/requirements/environment.yaml index af4f6f8..51bdd94 100644 --- a/ci/requirements/environment.yaml +++ b/ci/requirements/environment.yaml @@ -2,11 +2,11 @@ name: xarray-array-testing-tests channels: - conda-forge dependencies: - - python=3.12 - ipython - pre-commit - pytest - pytest-reportlog + - pytest-cov - hypothesis - xarray - numpy diff --git a/pyproject.toml b/pyproject.toml index cb76175..2d387a6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "xarray-array-testing" -requires-python = ">= 3.12" +requires-python = ">= 3.11" license = {text = "Apache-2.0"} dependencies = [ "hypothesis", @@ -51,7 +51,7 @@ ignore = [ "E501", # E501: line too long - let black worry about that "E731", # E731: do not assign a lambda expression, use a def ] -fixable = ["I"] +fixable = ["I", "TID"] extend-safe-fixes = [ "TID252", # absolute imports ] diff --git a/xarray_array_testing/base.py b/xarray_array_testing/base.py new file mode 100644 index 0000000..2d04dbd --- /dev/null +++ b/xarray_array_testing/base.py @@ -0,0 +1,27 @@ +import abc +from abc import ABC +from types import ModuleType + +import numpy.testing as npt +from xarray.namedarray._typing import duckarray + + +class DuckArrayTestMixin(ABC): + @property + @abc.abstractmethod + def xp() -> ModuleType: + pass + + @property + @abc.abstractmethod + def array_type(self) -> type[duckarray]: + pass + + @staticmethod + @abc.abstractmethod + def array_strategy_fn(*, shape, dtype): + raise NotImplementedError("has to be overridden") + + @staticmethod + def assert_equal(a, b): + npt.assert_equal(a, b) diff --git a/xarray_array_testing/creation.py b/xarray_array_testing/creation.py new file mode 100644 index 0000000..291e082 --- /dev/null +++ b/xarray_array_testing/creation.py @@ -0,0 +1,13 @@ +import hypothesis.strategies as st +import xarray.testing.strategies as xrst +from hypothesis import given + +from xarray_array_testing.base import DuckArrayTestMixin + + +class CreationTests(DuckArrayTestMixin): + @given(st.data()) + def test_create_variable(self, data): + variable = data.draw(xrst.variables(array_strategy_fn=self.array_strategy_fn)) + + assert isinstance(variable.data, self.array_type) diff --git a/xarray_array_testing/reduction.py b/xarray_array_testing/reduction.py new file mode 100644 index 0000000..8e58949 --- /dev/null +++ b/xarray_array_testing/reduction.py @@ -0,0 +1,33 @@ +from contextlib import nullcontext + +import hypothesis.strategies as st +import xarray.testing.strategies as xrst +from hypothesis import given + +from xarray_array_testing.base import DuckArrayTestMixin + + +class ReductionTests(DuckArrayTestMixin): + @staticmethod + def expected_errors(op, **parameters): + return nullcontext() + + @given(st.data()) + def test_variable_mean(self, data): + variable = data.draw(xrst.variables(array_strategy_fn=self.array_strategy_fn)) + + with self.expected_errors("mean", variable=variable): + actual = variable.mean().data + expected = self.xp.mean(variable.data) + + self.assert_equal(actual, expected) + + @given(st.data()) + def test_variable_prod(self, data): + variable = data.draw(xrst.variables(array_strategy_fn=self.array_strategy_fn)) + + with self.expected_errors("prod", variable=variable): + actual = variable.prod().data + expected = self.xp.prod(variable.data) + + self.assert_equal(actual, expected) diff --git a/xarray_array_testing/tests/test_numpy.py b/xarray_array_testing/tests/test_numpy.py new file mode 100644 index 0000000..2a9d95b --- /dev/null +++ b/xarray_array_testing/tests/test_numpy.py @@ -0,0 +1,34 @@ +from types import ModuleType + +import hypothesis.strategies as st +import numpy as np + +from xarray_array_testing.base import DuckArrayTestMixin +from xarray_array_testing.creation import CreationTests +from xarray_array_testing.reduction import ReductionTests + + +def create_numpy_array(*, shape, dtype): + return st.builds(np.ones, shape=st.just(shape), dtype=st.just(dtype)) + + +class NumpyTestMixin(DuckArrayTestMixin): + @property + def xp(self) -> ModuleType: + return np + + @property + def array_type(self) -> type[np.ndarray]: + return np.ndarray + + @staticmethod + def array_strategy_fn(*, shape, dtype): + return create_numpy_array(shape=shape, dtype=dtype) + + +class TestCreationNumpy(CreationTests, NumpyTestMixin): + pass + + +class TestReductionNumpy(ReductionTests, NumpyTestMixin): + pass
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: