test_edge_detection.py measures well on paper (87 tests, 100% branch coverage of xrspatial/edge_detection.py with JIT disabled) but several input classes never appear in it. Found during a test-coverage audit of the module. Related sibling issues from the same audit: #3672 (benchmarks), #3674/#3676 (docstrings), #3675 (style), #3677 (scipy golden values). This one is about input-space gaps only.
Inf input: grep -ci inf xrspatial/tests/test_edge_detection.py returns 0. An inf cell propagates inf and NaN (from inf minus inf) through the 3x3 kernels. Verified all backends agree on this; nothing pins it.
NaN placement and NaN on GPU/dask: NaN input is only tested at an interior cell, only on the numpy backend. No test puts a NaN at the raster edge where it interacts with 'nearest'/'reflect'/'wrap' padding, and the cross-backend equivalence tests (cupy, dask+numpy, dask+cupy) all run on NaN-free ramp data. NaN-input backend divergence has shipped elsewhere in the library before (kde, #3628), so the parity tests should include NaN.
Degenerate shapes: the smallest raster tested is 3x3. 1x1, 1xN and Nx1 never appear. With boundary='nan' a 1x1 input comes back all-NaN; with 'reflect' it comes back 0. A (0, N) empty raster passes through and returns an empty result. None of this is asserted.
Invalid boundary: aspect, morphology, diffusion and bilateral each have a test that boundary='invalid' raises ValueError. edge_detection has none.
Dask chunking: both dask tests use a single chunk equal to the full array (chunks=(5, 6) on a 5x6 raster, chunks=(8, 10) on 8x10), so chunk-boundary stitching in the map_overlap path is never exercised from this module's tests, on dask+numpy or dask+cupy. The accuracy audit probed multi-chunk grids and found them correct, so this is a test gap, not a bug.
Dim names: outputs pass through agg.dims, but only the default y/x dims are tested. A regression that hardcoded dims=['y', 'x'] would pass today's suite.
I probed every case above on a CUDA host: numpy, cupy, dask+numpy and dask+cupy all agree, including NaN-at-corner under all four boundary modes and multi-chunk grids. So the source is fine today and this is test-only work: pin the current behavior so regressions in convolve_2d or the wrappers get caught here.
Probe excerpt (numpy vs dask+numpy chunks=(3, 4), NaN at corner and interior):
sobel_x boundary=nan: numpy==dask(multichunk) -> True
sobel_x boundary=nearest: numpy==dask(multichunk) -> True
... (all 20 func x mode combinations True, same for cupy and dask+cupy)
sobel_x 1x1 numpy: [[nan]]
sobel_x 1x1 boundary=reflect: [[0.]]
sobel_x boundary='bogus': ValueError: boundary must be one of ('nan', 'nearest', 'reflect', 'wrap'), got 'bogus'
test_edge_detection.py measures well on paper (87 tests, 100% branch coverage of xrspatial/edge_detection.py with JIT disabled) but several input classes never appear in it. Found during a test-coverage audit of the module. Related sibling issues from the same audit: #3672 (benchmarks), #3674/#3676 (docstrings), #3675 (style), #3677 (scipy golden values). This one is about input-space gaps only.
Inf input:
grep -ci inf xrspatial/tests/test_edge_detection.pyreturns 0. An inf cell propagates inf and NaN (from inf minus inf) through the 3x3 kernels. Verified all backends agree on this; nothing pins it.NaN placement and NaN on GPU/dask: NaN input is only tested at an interior cell, only on the numpy backend. No test puts a NaN at the raster edge where it interacts with 'nearest'/'reflect'/'wrap' padding, and the cross-backend equivalence tests (cupy, dask+numpy, dask+cupy) all run on NaN-free ramp data. NaN-input backend divergence has shipped elsewhere in the library before (kde, #3628), so the parity tests should include NaN.
Degenerate shapes: the smallest raster tested is 3x3. 1x1, 1xN and Nx1 never appear. With boundary='nan' a 1x1 input comes back all-NaN; with 'reflect' it comes back 0. A (0, N) empty raster passes through and returns an empty result. None of this is asserted.
Invalid boundary: aspect, morphology, diffusion and bilateral each have a test that boundary='invalid' raises ValueError. edge_detection has none.
Dask chunking: both dask tests use a single chunk equal to the full array (chunks=(5, 6) on a 5x6 raster, chunks=(8, 10) on 8x10), so chunk-boundary stitching in the map_overlap path is never exercised from this module's tests, on dask+numpy or dask+cupy. The accuracy audit probed multi-chunk grids and found them correct, so this is a test gap, not a bug.
Dim names: outputs pass through agg.dims, but only the default y/x dims are tested. A regression that hardcoded dims=['y', 'x'] would pass today's suite.
I probed every case above on a CUDA host: numpy, cupy, dask+numpy and dask+cupy all agree, including NaN-at-corner under all four boundary modes and multi-chunk grids. So the source is fine today and this is test-only work: pin the current behavior so regressions in convolve_2d or the wrappers get caught here.
Probe excerpt (numpy vs dask+numpy chunks=(3, 4), NaN at corner and interior):