Testing¶
Running tests¶
# All tests (CPU path — no GPU required)
uv run pytest
# GPU kernel tests only (requires CUDA GPU)
uv run pytest -m gpu
# Specific module
uv run pytest tests/test_raster_algebra.py
# Verbose with short tracebacks
uv run pytest -v --tb=short
Test structure¶
File |
Coverage |
Lines |
|---|---|---|
|
GeoKey parsing, affine conversion |
153 |
|
nvImageCodec decode, format support |
218 |
|
Add/sub/mul/div, nodata, focal ops |
217 |
|
OwnedRasterArray, residency, diagnostics |
418 |
|
Read/write via rasterio, metadata |
277 |
|
CCL, connectivity, sieve, morphology |
672 |
|
Polygonize CPU/GPU, ring orientation |
416 |
|
GridSpec, CPU/GPU rasterize |
138 |
|
Zonal stats, GPU/CPU dispatch |
312 |
GPU test marker¶
Tests that require a CUDA GPU are marked with @pytest.mark.gpu:
@pytest.mark.gpu
def test_label_gpu():
...
GPU tests auto-skip when CuPy is not available. In CI, only CPU tests run (no GPU hardware). GPU tests must be run locally before merging.
Test patterns¶
CPU vs GPU comparison — run the same operation on CPU and GPU, assert results match within tolerance
Roundtrip — write then read, verify data preserved
Nodata propagation — verify nodata sentinel values flow through operations
Edge cases — single-pixel rasters, all-nodata, connectivity variants
Linting¶
# Check
uv run ruff check src/ tests/
# Format
uv run ruff format src/ tests/
# Format check (CI uses this)
uv run ruff format --check src/ tests/
CI¶
GitHub Actions runs on every push/PR to main:
Test job — Python 3.12 + 3.13 matrix,
pytest --tb=short -m "not gpu"Lint job —
ruff check+ruff format --check
No GPU tests in CI (no GPU hardware). GPU tests are a local-only gate.