Commit 1ba3307b authored by Turner, Sean's avatar Turner, Sean
Browse files

Update CLAUDE.md testing section with full test suite details

parent 3fc1f96f
Loading
Loading
Loading
Loading
+20 −52
Original line number Diff line number Diff line
@@ -74,62 +74,30 @@ After any major code changes to `src/helpers.rs` or `src/lib.rs`, run the test s
# Rebuild the module first
uv pip install -e .

# Run the HPF interpolation tests
uv run python -m pytest tests/test_hpf.py -v

# Quick smoke test with the toy example
uv run python -c "
import powersheds
from dataclasses import dataclass

@dataclass
class ReservoirData:
    object_type: str
    capacity: float
    initial_pool_elevation: float
    min_power_pool: float
    set_storage: list
    set_elevation: list
    hpf_h: list
    hpf_p: list
    hpf_q: list
    tailwater_elevation: float
    max_release: float
    min_release: float
    catchment_inflow: list
    target_power: list
    simulation_order: int
    downstream_object: str

@dataclass
class CascadeData:
    reservoirs: dict
    rivers: dict
    confluences: dict

res = ReservoirData(
    object_type='reservoir', simulation_order=1, downstream_object='NA',
    capacity=500.0, initial_pool_elevation=200.0, min_power_pool=190.0,
    tailwater_elevation=150.0, max_release=2.0, min_release=0.0,
    set_storage=[0.0, 250.0, 500.0], set_elevation=[180.0, 195.0, 210.0],
    catchment_inflow=[0.2]*24, target_power=[50.0]*24,
    hpf_h=[40,40,40,60,60,60], hpf_p=[0,50,100,0,50,100], hpf_q=[0,60,120,0,45,90])
result = powersheds.simulate_cascade(CascadeData(reservoirs={'Demo': res}, rivers={}, confluences={}))
import math
assert not any(math.isnan(v) for v in result['Demo']['actual_power']), 'NA values found!'
print('Smoke test passed')
"
# Run all tests (117 tests)
uv run python -m pytest tests/ -v

# Run a specific test file
uv run python -m pytest tests/test_cascade.py -v
```

**Test Coverage**:
- `tests/test_hpf.py` - HPF bilinear interpolation tests (74 tests)
  - Grid corner, edge, and interior roundtrip tests
  - Statistical robustness with random (H, P) pairs
  - Performance benchmarks
  - Edge cases (zero power, empty tables, etc.)
**Test Coverage** (117 tests across 7 files):
- `tests/test_hpf.py` - HPF bilinear interpolation (74 tests): grid corner/edge/interior roundtrips, statistical robustness, performance benchmarks, edge cases
- `tests/test_cascade.py` - Full cascade integration (13 tests): output structure, multi-reservoir routing, simulation ordering, mass balance, physical invariants, Cumberland NaN check
- `tests/test_simulate_timestep.py` - Per-timestep reservoir constraints (10 tests): below power pool, min/max release, insufficient water, spill, mass balance, unconstrained power equality
- `tests/test_interpolation.py` - Storage-elevation interpolation (10 tests): breakpoints, midpoints, clamping, roundtrip, monotonicity, Cumberland validation
- `tests/test_river_confluence.py` - Flow routing (6 tests): river lag, legacy flows, lag=0 passthrough, legacy length mismatch, confluence summation
- `tests/test_regression.py` - Regression tests (2 tests): Cumberland golden baseline, CLAUDE.md smoke test
- `tests/test_unit_conversion.py` - Unit conversion (2 tests): cumecs to Mm3/hr at known grid points

**Test Infrastructure**:
- `tests/helpers.py` - Shared dataclasses (`ReservoirData`, `RiverData`, `ConfluenceData`, `CascadeData`), factory functions (`make_reservoir`, `make_cascade`, `run_single_reservoir`), analytical helpers
- `tests/conftest.py` - Session-scoped Cumberland cascade fixtures
- `tests/fixtures/cumberland_baseline.json` - Golden baseline for regression testing
- `tests/TEST_DOCUMENTATION.md` - Detailed documentation of every test

**Known Limitations**:
- Some HPF tables have flat regions where multiple P values produce the same Q. In these regions, the reverse function (QP) cannot uniquely determine P, resulting in roundtrip errors up to ~1 MW. This is a physical limitation of the data, not a bug.
- Some HPF tables have flat regions where multiple P values produce the same Q. In these regions, the reverse function (Q->P) cannot uniquely determine P, resulting in roundtrip errors up to ~1 MW. This is a physical limitation of the data, not a bug.

## Dependencies