Skip to content

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 — the pytest workflow (fixtures and markers) and the import geocase public 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 with pytest.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

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 in docs/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.

Next reads