| """Shared test fixtures for Aperture tests.""" |
| from __future__ import annotations |
|
|
| import numpy as np |
| import pytest |
|
|
|
|
| @pytest.fixture |
| def synthetic_monthly_raster(tmp_path): |
| """Create a synthetic multi-band GeoTIFF with 12 monthly bands. |
| |
| Returns a factory function: call with (n_bands, shape, fill_fn) to get a path. |
| fill_fn(band_idx) -> 2D numpy array. |
| """ |
| import rasterio |
| from rasterio.transform import from_bounds |
|
|
| def _make( |
| n_bands: int = 12, |
| shape: tuple[int, int] = (100, 100), |
| fill_fn=None, |
| bbox: tuple[float, ...] = (37.8, 2.08, 37.88, 2.17), |
| ) -> str: |
| if fill_fn is None: |
| fill_fn = lambda i: np.random.default_rng(i).uniform(0.2, 0.8, shape).astype(np.float32) |
|
|
| path = str(tmp_path / f"synthetic_{n_bands}bands.tif") |
| transform = from_bounds(*bbox, shape[1], shape[0]) |
| with rasterio.open( |
| path, "w", driver="GTiff", |
| height=shape[0], width=shape[1], |
| count=n_bands, dtype="float32", |
| crs="EPSG:4326", transform=transform, |
| nodata=-9999.0, |
| ) as dst: |
| for i in range(n_bands): |
| dst.write(fill_fn(i), i + 1) |
| return path |
|
|
| return _make |
|
|
|
|
| @pytest.fixture |
| def mock_product_result(): |
| """Factory for ProductResult with sensible defaults.""" |
| from app.models import ProductResult, StatusLevel, TrendDirection, ConfidenceLevel |
|
|
| def _make(**overrides): |
| defaults = dict( |
| product_id="ndvi", |
| headline="Test headline", |
| status=StatusLevel.GREEN, |
| trend=TrendDirection.STABLE, |
| confidence=ConfidenceLevel.HIGH, |
| map_layer_path="/tmp/fake.tif", |
| chart_data={"dates": [], "values": []}, |
| summary="Test summary", |
| methodology="Test methodology", |
| limitations=["Test limitation"], |
| data_source="satellite", |
| anomaly_months=0, |
| z_score_current=0.0, |
| hotspot_pct=0.0, |
| confidence_factors={}, |
| ) |
| defaults.update(overrides) |
| return ProductResult(**defaults) |
|
|
| return _make |
|
|