add marks to all tests

This commit is contained in:
sneakers-the-rat 2024-09-23 13:28:38 -07:00
parent 9026eb700f
commit 8cc2574399
Signed by untrusted user who does not match committer: jonny
GPG key ID: 6DCB96EF1E4D232D
14 changed files with 101 additions and 36 deletions

View file

@ -116,7 +116,13 @@ markers = [
"dtype: mark test related to dtype validation", "dtype: mark test related to dtype validation",
"shape: mark test related to shape validation", "shape: mark test related to shape validation",
"json_schema: mark test related to json schema generation", "json_schema: mark test related to json schema generation",
"serialization: mark test related to serialization" "serialization: mark test related to serialization",
"proxy: test for proxy class in any interface",
"dask: dask interface",
"hdf5: hdf5 interface",
"numpy: numpy interface",
"video: video interface",
"zarr: zarr interface",
] ]
[tool.ruff] [tool.ruff]

View file

@ -61,7 +61,7 @@ class DaskInterface(Interface):
""" """
check if array is a dask array check if array is a dask array
""" """
if DaskArray is None: if DaskArray is None: # pragma: no cover - no tests for interface deps atm
return False return False
elif isinstance(array, DaskArray): elif isinstance(array, DaskArray):
return True return True

View file

@ -83,6 +83,7 @@ STRING: TypeAlias = NDArray[Shape["*, *, *"], str]
MODEL: TypeAlias = NDArray[Shape["*, *, *"], BasicModel] MODEL: TypeAlias = NDArray[Shape["*, *, *"], BasicModel]
@pytest.mark.shape
@pytest.fixture( @pytest.fixture(
scope="module", scope="module",
params=[ params=[
@ -120,6 +121,7 @@ def shape_cases(request) -> ValidationCase:
return request.param return request.param
@pytest.mark.dtype
@pytest.fixture( @pytest.fixture(
scope="module", scope="module",
params=[ params=[

View file

@ -104,6 +104,7 @@ def model_blank() -> Type[BaseModel]:
return BlankModel return BlankModel
@pytest.mark.hdf5
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def hdf5_file(tmp_output_dir_func) -> h5py.File: def hdf5_file(tmp_output_dir_func) -> h5py.File:
h5f_file = tmp_output_dir_func / "h5f.h5" h5f_file = tmp_output_dir_func / "h5f.h5"
@ -112,6 +113,7 @@ def hdf5_file(tmp_output_dir_func) -> h5py.File:
h5f.close() h5f.close()
@pytest.mark.hdf5
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def hdf5_array( def hdf5_array(
hdf5_file, request hdf5_file, request
@ -154,6 +156,7 @@ def hdf5_array(
return _hdf5_array return _hdf5_array
@pytest.mark.zarr
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def zarr_nested_array(tmp_output_dir_func) -> ZarrArrayPath: def zarr_nested_array(tmp_output_dir_func) -> ZarrArrayPath:
"""Zarr array within a nested array""" """Zarr array within a nested array"""
@ -164,6 +167,7 @@ def zarr_nested_array(tmp_output_dir_func) -> ZarrArrayPath:
return ZarrArrayPath(file=file, path=path) return ZarrArrayPath(file=file, path=path)
@pytest.mark.zarr
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def zarr_array(tmp_output_dir_func) -> Path: def zarr_array(tmp_output_dir_func) -> Path:
file = tmp_output_dir_func / "array.zarr" file = tmp_output_dir_func / "array.zarr"
@ -172,6 +176,7 @@ def zarr_array(tmp_output_dir_func) -> Path:
return file return file
@pytest.mark.video
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def avi_video(tmp_path) -> Callable[[Tuple[int, int], int, bool], Path]: def avi_video(tmp_path) -> Callable[[Tuple[int, int], int, bool], Path]:
video_path = tmp_path / "test.avi" video_path = tmp_path / "test.avi"

View file

@ -12,24 +12,44 @@ from numpydantic import interface, NDArray
@pytest.fixture( @pytest.fixture(
scope="function", scope="function",
params=[ params=[
([[1, 2], [3, 4]], interface.NumpyInterface), pytest.param(
(np.zeros((3, 4)), interface.NumpyInterface), ([[1, 2], [3, 4]], interface.NumpyInterface),
("hdf5_array", interface.H5Interface), marks=pytest.mark.numpy,
(da.random.random((10, 10)), interface.DaskInterface), id="numpy-list",
(zarr.ones((10, 10)), interface.ZarrInterface), ),
("zarr_nested_array", interface.ZarrInterface), pytest.param(
("zarr_array", interface.ZarrInterface), (np.zeros((3, 4)), interface.NumpyInterface),
("avi_video", interface.VideoInterface), marks=pytest.mark.numpy,
], id="numpy",
ids=[ ),
"numpy_list", pytest.param(
"numpy", ("hdf5_array", interface.H5Interface),
"H5ArrayPath", marks=pytest.mark.hdf5,
"dask", id="h5-array-path",
"zarr_memory", ),
"zarr_nested", pytest.param(
"zarr_array", (da.random.random((10, 10)), interface.DaskInterface),
"video", marks=pytest.mark.dask,
id="dask",
),
pytest.param(
(zarr.ones((10, 10)), interface.ZarrInterface),
marks=pytest.mark.zarr,
id="zarr-memory",
),
pytest.param(
("zarr_nested_array", interface.ZarrInterface),
marks=pytest.mark.zarr,
id="zarr-nested",
),
pytest.param(
("zarr_array", interface.ZarrInterface),
marks=pytest.mark.zarr,
id="zarr-array",
),
pytest.param(
("avi_video", interface.VideoInterface), marks=pytest.mark.video, id="video"
),
], ],
) )
def interface_type(request) -> Tuple[NDArray, Type[interface.Interface]]: def interface_type(request) -> Tuple[NDArray, Type[interface.Interface]]:

View file

@ -1,5 +1,3 @@
import pdb
import pytest import pytest
import json import json
@ -11,6 +9,8 @@ from numpydantic.exceptions import DtypeError, ShapeError
from tests.conftest import ValidationCase from tests.conftest import ValidationCase
pytestmark = pytest.mark.dask
def dask_array(case: ValidationCase) -> da.Array: def dask_array(case: ValidationCase) -> da.Array:
if issubclass(case.dtype, BaseModel): if issubclass(case.dtype, BaseModel):
@ -42,14 +42,17 @@ def test_dask_check(interface_type):
assert not DaskInterface.check(interface_type[0]) assert not DaskInterface.check(interface_type[0])
@pytest.mark.shape
def test_dask_shape(shape_cases): def test_dask_shape(shape_cases):
_test_dask_case(shape_cases) _test_dask_case(shape_cases)
@pytest.mark.dtype
def test_dask_dtype(dtype_cases): def test_dask_dtype(dtype_cases):
_test_dask_case(dtype_cases) _test_dask_case(dtype_cases)
@pytest.mark.serialization
def test_dask_to_json(array_model): def test_dask_to_json(array_model):
array_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] array_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
array = da.array(array_list) array = da.array(array_list)

View file

@ -1,10 +0,0 @@
"""
Tests for dunder methods on all interfaces
"""
def test_dunder_len(all_interfaces):
"""
Each interface or proxy type should support __len__
"""
assert len(all_interfaces.array) == all_interfaces.array.shape[0]

View file

@ -14,6 +14,8 @@ from numpydantic.exceptions import DtypeError, ShapeError
from tests.conftest import ValidationCase from tests.conftest import ValidationCase
pytestmark = pytest.mark.hdf5
def hdf5_array_case( def hdf5_array_case(
case: ValidationCase, array_func, compound: bool = False case: ValidationCase, array_func, compound: bool = False
@ -72,11 +74,13 @@ def test_hdf5_check_not_hdf5(tmp_path):
assert not H5Interface.check(spec) assert not H5Interface.check(spec)
@pytest.mark.shape
@pytest.mark.parametrize("compound", [True, False]) @pytest.mark.parametrize("compound", [True, False])
def test_hdf5_shape(shape_cases, hdf5_array, compound): def test_hdf5_shape(shape_cases, hdf5_array, compound):
_test_hdf5_case(shape_cases, hdf5_array, compound) _test_hdf5_case(shape_cases, hdf5_array, compound)
@pytest.mark.dtype
@pytest.mark.parametrize("compound", [True, False]) @pytest.mark.parametrize("compound", [True, False])
def test_hdf5_dtype(dtype_cases, hdf5_array, compound): def test_hdf5_dtype(dtype_cases, hdf5_array, compound):
_test_hdf5_case(dtype_cases, hdf5_array, compound) _test_hdf5_case(dtype_cases, hdf5_array, compound)
@ -90,6 +94,7 @@ def test_hdf5_dataset_not_exists(hdf5_array, model_blank):
assert "no array found" in e assert "no array found" in e
@pytest.mark.proxy
def test_assignment(hdf5_array, model_blank): def test_assignment(hdf5_array, model_blank):
array = hdf5_array() array = hdf5_array()
@ -101,6 +106,7 @@ def test_assignment(hdf5_array, model_blank):
assert (model.array[1:3, 2:4] == 10).all() assert (model.array[1:3, 2:4] == 10).all()
@pytest.mark.serialization
@pytest.mark.parametrize("round_trip", (True, False)) @pytest.mark.parametrize("round_trip", (True, False))
def test_to_json(hdf5_array, array_model, round_trip): def test_to_json(hdf5_array, array_model, round_trip):
""" """
@ -125,6 +131,8 @@ def test_to_json(hdf5_array, array_model, round_trip):
assert json_dumped == instance.array[:].tolist() assert json_dumped == instance.array[:].tolist()
@pytest.mark.dtype
@pytest.mark.proxy
def test_compound_dtype(tmp_path): def test_compound_dtype(tmp_path):
""" """
hdf5 proxy indexes compound dtypes as single fields when field is given hdf5 proxy indexes compound dtypes as single fields when field is given
@ -159,6 +167,8 @@ def test_compound_dtype(tmp_path):
assert all(instance.array[1] == 2) assert all(instance.array[1] == 2)
@pytest.mark.dtype
@pytest.mark.proxy
@pytest.mark.parametrize("compound", [True, False]) @pytest.mark.parametrize("compound", [True, False])
def test_strings(hdf5_array, compound): def test_strings(hdf5_array, compound):
""" """
@ -178,6 +188,8 @@ def test_strings(hdf5_array, compound):
assert all(instance.array[1] == "sup") assert all(instance.array[1] == "sup")
@pytest.mark.dtype
@pytest.mark.proxy
@pytest.mark.parametrize("compound", [True, False]) @pytest.mark.parametrize("compound", [True, False])
def test_datetime(hdf5_array, compound): def test_datetime(hdf5_array, compound):
""" """

View file

@ -66,3 +66,10 @@ def test_interface_roundtrip_json(all_interfaces, round_trip):
assert model.array.dtype == all_interfaces.array.dtype assert model.array.dtype == all_interfaces.array.dtype
else: else:
assert np.array_equal(model.array, np.array(all_interfaces.array)) assert np.array_equal(model.array, np.array(all_interfaces.array))
def test_dunder_len(all_interfaces):
"""
Each interface or proxy type should support __len__
"""
assert len(all_interfaces.array) == all_interfaces.array.shape[0]

View file

@ -5,6 +5,8 @@ from numpydantic.exceptions import DtypeError, ShapeError
from tests.conftest import ValidationCase from tests.conftest import ValidationCase
pytestmark = pytest.mark.numpy
def numpy_array(case: ValidationCase) -> np.ndarray: def numpy_array(case: ValidationCase) -> np.ndarray:
if issubclass(case.dtype, BaseModel): if issubclass(case.dtype, BaseModel):
@ -22,10 +24,12 @@ def _test_np_case(case: ValidationCase):
case.model(array=array) case.model(array=array)
@pytest.mark.shape
def test_numpy_shape(shape_cases): def test_numpy_shape(shape_cases):
_test_np_case(shape_cases) _test_np_case(shape_cases)
@pytest.mark.dtype
def test_numpy_dtype(dtype_cases): def test_numpy_dtype(dtype_cases):
_test_np_case(dtype_cases) _test_np_case(dtype_cases)

View file

@ -14,6 +14,8 @@ from numpydantic import NDArray, Shape
from numpydantic import dtype as dt from numpydantic import dtype as dt
from numpydantic.interface.video import VideoProxy from numpydantic.interface.video import VideoProxy
pytestmark = pytest.mark.video
@pytest.mark.parametrize("input_type", [str, Path]) @pytest.mark.parametrize("input_type", [str, Path])
def test_video_validation(avi_video, input_type): def test_video_validation(avi_video, input_type):
@ -49,6 +51,7 @@ def test_video_from_videocapture(avi_video):
opened_vid.release() opened_vid.release()
@pytest.mark.shape
def test_video_wrong_shape(avi_video): def test_video_wrong_shape(avi_video):
shape = (100, 50) shape = (100, 50)
@ -65,6 +68,7 @@ def test_video_wrong_shape(avi_video):
instance = MyModel(array=vid) instance = MyModel(array=vid)
@pytest.mark.proxy
def test_video_getitem(avi_video): def test_video_getitem(avi_video):
""" """
Should be able to get individual frames and slices as if it were a normal array Should be able to get individual frames and slices as if it were a normal array
@ -127,6 +131,7 @@ def test_video_getitem(avi_video):
instance.array[5] = 10 instance.array[5] = 10
@pytest.mark.proxy
def test_video_attrs(avi_video): def test_video_attrs(avi_video):
"""Should be able to access opencv properties""" """Should be able to access opencv properties"""
shape = (100, 50) shape = (100, 50)
@ -142,6 +147,7 @@ def test_video_attrs(avi_video):
assert int(instance.array.get(cv2.CAP_PROP_POS_FRAMES)) == 5 assert int(instance.array.get(cv2.CAP_PROP_POS_FRAMES)) == 5
@pytest.mark.proxy
def test_video_close(avi_video): def test_video_close(avi_video):
"""Should close and reopen video file if needed""" """Should close and reopen video file if needed"""
shape = (100, 50) shape = (100, 50)

View file

@ -6,13 +6,14 @@ import zarr
from pydantic import BaseModel, ValidationError from pydantic import BaseModel, ValidationError
from numcodecs import Pickle from numcodecs import Pickle
from numpydantic.interface import ZarrInterface from numpydantic.interface import ZarrInterface
from numpydantic.interface.zarr import ZarrArrayPath from numpydantic.interface.zarr import ZarrArrayPath
from numpydantic.exceptions import DtypeError, ShapeError from numpydantic.exceptions import DtypeError, ShapeError
from tests.conftest import ValidationCase from tests.conftest import ValidationCase
pytestmark = pytest.mark.zarr
@pytest.fixture() @pytest.fixture()
def dir_array(tmp_output_dir_func) -> zarr.DirectoryStore: def dir_array(tmp_output_dir_func) -> zarr.DirectoryStore:
@ -87,10 +88,12 @@ def test_zarr_check(interface_type):
assert not ZarrInterface.check(interface_type[0]) assert not ZarrInterface.check(interface_type[0])
@pytest.mark.shape
def test_zarr_shape(store, shape_cases): def test_zarr_shape(store, shape_cases):
_test_zarr_case(shape_cases, store) _test_zarr_case(shape_cases, store)
@pytest.mark.dtype
def test_zarr_dtype(dtype_cases, store): def test_zarr_dtype(dtype_cases, store):
_test_zarr_case(dtype_cases, store) _test_zarr_case(dtype_cases, store)

View file

@ -41,6 +41,7 @@ def test_ndarray_type():
instance = Model(array=np.zeros((2, 3)), array_any=np.ones((3, 4, 5))) instance = Model(array=np.zeros((2, 3)), array_any=np.ones((3, 4, 5)))
@pytest.mark.dtype
@pytest.mark.json_schema @pytest.mark.json_schema
def test_schema_unsupported_type(): def test_schema_unsupported_type():
""" """
@ -57,10 +58,11 @@ def test_schema_unsupported_type():
} }
@pytest.mark.dtype
@pytest.mark.json_schema @pytest.mark.json_schema
def test_schema_tuple(): def test_schema_tuple():
""" """
Types specified as tupled should have their schemas as a union Types specified as tuples should have their schemas as a union
""" """
class Model(BaseModel): class Model(BaseModel):
@ -75,6 +77,7 @@ def test_schema_tuple():
assert all([i["minimum"] == 0 for i in conditions]) assert all([i["minimum"] == 0 for i in conditions])
@pytest.mark.dtype
@pytest.mark.json_schema @pytest.mark.json_schema
def test_schema_number(): def test_schema_number():
""" """
@ -119,12 +122,12 @@ def test_ndarray_union():
instance = Model(array=np.random.random((5, 10, 4, 6))) instance = Model(array=np.random.random((5, 10, 4, 6)))
@pytest.mark.shape
@pytest.mark.dtype
@pytest.mark.parametrize("dtype", dtype.Number) @pytest.mark.parametrize("dtype", dtype.Number)
def test_ndarray_unparameterized(dtype): def test_ndarray_unparameterized(dtype):
""" """
NDArray without any parameters is any shape, any type NDArray without any parameters is any shape, any type
Returns:
""" """
class Model(BaseModel): class Model(BaseModel):
@ -138,6 +141,7 @@ def test_ndarray_unparameterized(dtype):
_ = Model(array=np.zeros(dim_sizes, dtype=dtype)) _ = Model(array=np.zeros(dim_sizes, dtype=dtype))
@pytest.mark.shape
def test_ndarray_any(): def test_ndarray_any():
""" """
using :class:`typing.Any` in for the shape means any shape using :class:`typing.Any` in for the shape means any shape
@ -249,6 +253,7 @@ def test_json_schema_dtype_single(dtype, array_model):
@pytest.mark.dtype @pytest.mark.dtype
@pytest.mark.json_schema
@pytest.mark.parametrize( @pytest.mark.parametrize(
"dtype,expected", "dtype,expected",
[ [

View file

@ -9,6 +9,8 @@ import numpy as np
from numpydantic import NDArray, Shape from numpydantic import NDArray, Shape
pytestmark = pytest.mark.shape
@pytest.mark.parametrize( @pytest.mark.parametrize(
"shape,valid", "shape,valid",