GeoCase¶
GeoCase is an open geospatial testing toolkit and case catalog for realistic, reproducible, parameterized tests.
Status: 1.0.0 is available on PyPI —
pip install geocase. The compatibility promise covers two surfaces — thepytestworkflow (fixtures and markers) and theimport geocasepublic API. 174 bundled cases, 5.1 MB. Remote dataset transport is deferred to v1.1; see the changelog.
Most spatial tests use overly simple geometries or ad hoc local files. GeoCase provides a curated catalog of compact but behaviorally meaningful cases that can be selected into pytest suites by metadata such as category, risk type, test tier, format, and storage class.
Most of the catalog is about geometry, CRS and georeferencing conventions — rotated geotransforms, bottom-up rasters, pixel-is-area versus pixel-is-point anchoring, antimeridian footprints, CRS mismatch, EPSG axis order, NoData. Radiometric conventions for Sentinel-1 and Sentinel-2 are one vertical inside that, not the thesis.
It works with plain GDAL. case.primary_path is an ordinary filesystem path, so
gdal.Open reads a case directly, and the base install needs only pydantic, pyyaml and
geofacts. The extras are for the convenience loaders, not for reading the files. If your
codebase moves pixels and geometry around on a GDAL-native stack, you are the audience this
corpus serves best.
Core ideas¶
-
Cases, not random files
Every sample is a self-contained test case with metadata describing why it exists. -
Parameterized testing first
GeoCase is designed to work naturally withpytest.mark.parametrize(...). -
Metadata-driven selection
Users select cases by tags, risk types, categories, and suites rather than hardcoding paths everywhere. -
Small bundled core, larger optional catalog
Tiny core cases ship with the package. Larger realistic samples can be fetched on demand.
Start here¶
- Browse all 174 cases — the case catalog, filterable and sortable, with coverage maps
- New users:
getting-started.md - Testing a real function:
testing-your-function-with-geocase.md - Finding cases by metadata:
case-discovery.md - Reusable checks:
assertions-reference.md - Example tests:
examples-index.md - Adding new cases:
adding-a-case.md
Documentation map¶
Each folder under docs/ holds one kind of document:
- User guides at the top level explain how to select cases, write tests, and use GeoCase day to day.
docs/contributing/— how to work on GeoCase: workflow, conventions, and maintainer practices.docs/plans/— what is planned and in what order, including the roadmap. Superseded plans stay indocs/plans/archive/as an implementation log.docs/design/— future-facing designs for things that do not exist yet, such as a case-recommendation service. Kept in the repository and readable on GitHub, but not published here, so that a proposal is never mistaken for a shipping feature.docs/reference/— descriptive maps of the project as it exists today, such as the codebase summary.docs/_generated/— pages built by scripts and gated in CI; never edit them by hand.
Example¶
import pytest
import geocase
@pytest.mark.parametrize(
"meta",
geocase.list_cases(category="vector", test_tier="unit"),
ids=lambda m: m.id,
)
def test_vector_loading(meta):
if not meta.assertions.expect_loadable:
pytest.skip(f"{meta.id} is a case that should not load cleanly")
gdf = geocase.load_case(meta.id).load()
assert len(gdf) > 0
list_cases() returns metadata, and load_case() turns a case id into
something loadable. The expect_loadable check matters because some cases
exist precisely to break loaders. See
using-parameterized-tests.md for both points.