Metadata-Version: 2.4
Name: geocase
Version: 1.0.0rc1
Summary: A curated library of geospatial test cases for automated and parameterized testing.
Project-URL: Homepage, https://github.com/farzinashouri/geocase
Project-URL: Documentation, https://farzinashouri.github.io/geocase
Project-URL: Repository, https://github.com/farzinashouri/geocase
Project-URL: Issues, https://github.com/farzinashouri/geocase/issues
Project-URL: Changelog, https://github.com/farzinashouri/geocase/blob/main/CHANGELOG.md
Author: Farzin Ashouri
License-Expression: MIT
License-File: LICENSE
Keywords: geospatial,gis,pytest,test-cases,testing
Classifier: Development Status :: 5 - Production/Stable
Classifier: Framework :: Pytest
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: GIS
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.11
Requires-Dist: pydantic>=2.0
Requires-Dist: pyyaml>=6.0
Provides-Extra: all
Requires-Dist: geopandas>=0.14; extra == 'all'
Requires-Dist: netcdf4>=1.6; extra == 'all'
Requires-Dist: pyarrow>=14.0; extra == 'all'
Requires-Dist: rasterio>=1.3; extra == 'all'
Requires-Dist: shapely>=2.0; extra == 'all'
Requires-Dist: xarray>=2023.1; extra == 'all'
Provides-Extra: dev
Requires-Dist: geopandas>=0.14; extra == 'dev'
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: netcdf4>=1.6; extra == 'dev'
Requires-Dist: pyarrow>=14.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: rasterio>=1.3; extra == 'dev'
Requires-Dist: ruff<0.16,>=0.15.7; extra == 'dev'
Requires-Dist: shapely>=2.0; extra == 'dev'
Requires-Dist: types-pyyaml; extra == 'dev'
Requires-Dist: types-shapely; extra == 'dev'
Requires-Dist: xarray>=2023.1; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.0; extra == 'docs'
Requires-Dist: mkdocs>=1.5; extra == 'docs'
Provides-Extra: netcdf
Requires-Dist: netcdf4>=1.6; extra == 'netcdf'
Requires-Dist: xarray>=2023.1; extra == 'netcdf'
Provides-Extra: raster
Requires-Dist: rasterio>=1.3; extra == 'raster'
Provides-Extra: vector
Requires-Dist: geopandas>=0.14; extra == 'vector'
Requires-Dist: pyarrow>=14.0; extra == 'vector'
Requires-Dist: shapely>=2.0; extra == 'vector'
Description-Content-Type: text/markdown

# GeoCase

GeoCase is a geospatial testing toolkit and case catalog for realistic, reproducible `pytest` tests.

> Status: **1.0**. The compatibility promise covers two surfaces — the `pytest` workflow (fixtures and markers) and the `import geocase` public API. 134 bundled cases, 4.2 MB. Remote dataset transport is deferred to v1.1; see the [changelog](CHANGELOG.md).

The main goal is simple: use plain `pytest` with a few GeoCase fixtures and markers to run your geospatial code against curated edge cases.

Instead of hand-picking random sample files, you select packaged cases (vector, raster, NetCDF) and run your function against scenarios such as CRS issues, dateline crossing, topology problems, and NoData behavior.

## Quick Start

### 1) Install

For local development in this repo:

```bash
pip install -e ".[dev]"
```

When a package release is published, install from the package index:

```bash
pip install "geocase[all]"
```

Or from conda-forge — note the extras are not packaged there, since bundling
GDAL would make the conda package far heavier than the PyPI equivalent:

```bash
conda install -c conda-forge geocase
```

### 2) Write a test with GeoCase markers

```python
import pytest


@pytest.mark.geocase_case("dateline_crossing_polygon")
def test_vector_case_loads(geocase_case) -> None:
    gdf = geocase_case.load()
    assert geocase_case.id == "dateline_crossing_polygon"
    assert gdf.crs is not None


@pytest.mark.geocase_select(category="raster")
def test_all_raster_cases_have_pixels(geocase) -> None:
    data, _, _ = geocase.read(1)
    assert data.size > 0
```

### 3) Run tests

```bash
pytest -v
```

Run only GeoCase-marked tests:

```bash
pytest -m "geocase_case or geocase_suite or geocase_select" -v
```

## CI Jobs

This repository uses GitHub Actions, defined in `.github/workflows/`.

`ci.yml` runs on pushes to `main` and on pull requests:

- `catalog` — catalog integrity checks (`build_case_index.py` smoke check,
  `validate_catalog.py`, fixture and checksum gates, generated-page freshness)
- `tests` — the whole `tests/` directory on Python 3.11 and 3.14, reporting
  coverage (not gated)
- `lint` — `ruff format --check` and `ruff check` over `src` and `tests`
- `typecheck` — `mypy src`
- `docs` — `mkdocs build --strict`

`release.yml` runs only on `vX.Y.Z` tags; see
[Releasing](contributing/releasing.md).

Local equivalents:

```bash
python scripts/build_case_index.py --check
python scripts/validate_catalog.py

python -m pytest tests -q
ruff format --check src tests && ruff check src tests
```

## Core Concepts

- `@pytest.mark.geocase_case(...)`: select explicit case IDs.
- `@pytest.mark.geocase_suite(...)`: use named suites.
- `@pytest.mark.geocase_select(...)`: select by metadata (`category`, `format`, `geometry_type`, `tags`, `risk_types_any`, etc.).
- `geocase`: auto-parameterized fixture (one invocation per resolved case).
- `geocase_case`: convenience fixture for exactly one resolved case.
- CLI tooling is optional; the primary workflow is plain `pytest`.

If a GeoCase marker is missing, resolves no cases, refers to an unknown suite, or `geocase_case` resolves more than one case, the plugin now raises a focused `pytest.UsageError` that explains what to fix.

## Learn More

- [`docs/getting-started.md`](docs/getting-started.md)
- [`docs/testing-your-function-with-geocase.md`](docs/testing-your-function-with-geocase.md)
- [`docs/case-discovery.md`](docs/case-discovery.md)
- [`docs/assertions-reference.md`](docs/assertions-reference.md)
- [`docs/examples-index.md`](docs/examples-index.md)
- [`docs/plans/development-plan.md`](docs/plans/development-plan.md)
- [`docs/contributing/workflow.md`](docs/contributing/workflow.md)
- [`docs/design/case-recommendation-service.md`](docs/design/case-recommendation-service.md)