Using parameterized tests¶
GeoCase is designed to make metadata-driven parameterization natural.
If you want help choosing filters, see case-discovery.md.
Metadata and cases are two different things¶
Every example below uses two functions, and it is worth knowing why:
geocase.list_cases(...)returns metadata —CaseMetadataobjects describing what each case is. Reading it opens no files and imports no geospatial library.geocase.load_case(case_id)returns a case — aVectorCase,RasterCase, orNetCDFCaseyou can call.load()or.open()on.
So you filter on metadata, then load the ones you selected. Metadata objects
have no .load() method; that separation is deliberate, and it keeps
collection cheap even when a filter matches most of the catalog.
The plugin's geocase fixture yields the loaded case directly, because by then
selection has already happened.
Select by metadata¶
Use list_cases(...) when you want to resolve matching cases directly in pytest.mark.parametrize(...).
import pytest
import geocase
@pytest.mark.parametrize(
"meta",
geocase.list_cases(category="vector", test_tier="unit"),
ids=lambda m: m.id,
)
def test_vector_cases_load(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
This pattern is useful when your test intent is broad, such as “all unit-tier vector cases should load”.
Mind the cases that are supposed to fail. A broad filter will sweep in
cases built to break loaders — unclosed_ring_polygon is one of the 103
unit-tier vector cases, and loading it raises a GEOSException by design.
meta.assertions.expect_loadable tells you which those are, so a broad test
can skip them rather than report a failure GeoCase intended.
Select by risk type¶
Risk types let you group by likely bug or failure mode.
import pytest
import geocase
@pytest.mark.parametrize(
"meta",
geocase.list_cases(risk_types_any=["bbox_misinterpretation"]),
ids=lambda m: m.id,
)
def test_bounds_handling(meta):
data = geocase.load_case(meta.id).load()
assert data is not None
Use a named suite¶
Use get_suite(...) when maintainers already define the group you want. It returns a
ResolvedSuite, whose .cases are metadata like list_cases() returns.
import pytest
import geocase
@pytest.mark.parametrize(
"meta",
geocase.get_suite("core-vector").cases,
ids=lambda m: m.id,
)
def test_core_vector_suite(meta):
gdf = geocase.load_case(meta.id).load()
assert gdf is not None
Suites are a good fit for stable CI coverage because they avoid repeating selector logic in many test files.
Use geocase.list_suites() to see every suite the package ships.
Combine GeoCase with reusable assertions¶
GeoCase works well with the helpers in geocase.assertions.
import pytest
import geocase
from geocase.assertions import assert_has_crs
@pytest.mark.parametrize(
"meta",
geocase.list_cases(category="vector", test_tier="unit"),
ids=lambda m: m.id,
)
def test_vector_cases_have_crs(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_has_crs(gdf)
See assertions-reference.md for a compact list of the available helpers.
Inspect a single case¶
show_case(...) prints a readable summary — useful when a parametrized run fails and
you want to know what the case actually is.
When to use list_cases(...) vs plugin markers¶
Both approaches are valid:
- use
list_cases(...)when you want explicitpytest.mark.parametrize(...)in the test body, - use
@pytest.mark.geocase_select(...)when you want GeoCase's plugin to handle parameterization for you, - use
@pytest.mark.geocase_suite(...)when you want a curated named group, - use
@pytest.mark.geocase_case(...)when you want exact case IDs.
With the markers, the geocase fixture hands your test a loaded case, so there is no
load_case(...) step to write.