Skip to content

chore: Add integration and unit tests for Python and .NET SDKs - #132

Closed
joakimia wants to merge 4 commits into
mainfrom
chore/add-integration-tests
Closed

chore: Add integration and unit tests for Python and .NET SDKs#132
joakimia wants to merge 4 commits into
mainfrom
chore/add-integration-tests

Conversation

@joakimia

@joakimia joakimia commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Expands the Python SDK with missing endpoint wrappers, introduces a full integration- and unit-test suite covering all Python endpoints, and adds test fake infrastructure for the .NET WhenHandlingTransientErrors test suite.


Python SDK

New endpoint wrappers

The following endpoints existed in the generated API client but were not exposed through the SDK wrapper or HeimdallApiClient. They are now fully implemented:

grid_insights.py / client.py

Method Type Description
get_currents Historical Current measurements for a line over a time range
get_conductor_temperatures Historical Conductor temperature measurements for a line
get_icing Historical Icing measurements for a line over a time range
get_sag_and_clearance Historical Sag and clearance measurements for a line
get_apparent_power Historical Apparent power measurements for a line
get_latest_apparent_power Latest Most recent apparent power measurement
get_icing_forecast Forecast Latest icing forecast for a line

capacity_monitoring.py / client.py

Method Type Description
get_heimdall_dlrs Historical Heimdall DLR values for a line over a time range
get_heimdall_aars Historical Heimdall AAR values for a line over a time range
get_circuit_ratings Historical Circuit ratings for a facility over a time range

Tests

Tests are split by stability:

  • Integration tests — only cover historical endpoints where the response is deterministic for a fixed time range. Tests run against the real API using the Heimdall Power Line (d67d2205-…) test fixture.
  • Unit tests — cover all latest and forecast endpoints using mocks, since these can return 404 when no recent data exists. Each endpoint is tested for:
    1. 200 OK → parsed response is returned
    2. 404 Not FoundHeimdallApiError(status_code=404) is raised
    3. 404 is not retried → time.sleep is never called

New test files:

File Type Coverage
tests/integration/test_when_fetching_capacity_monitoring.py Integration get_heimdall_dlrs, get_heimdall_aars, get_circuit_ratings + invalid-ID error paths
tests/integration/test_when_fetching_grid_insights.py Integration get_currents, get_conductor_temperatures, get_icing, get_sag_and_clearance, get_apparent_power + invalid-ID error path
tests/unit/test_latest_endpoints.py Unit All 12 latest/forecast methods on HeimdallApiClient — 200 OK, 404 raised, 404 not retried
tests/unit/test_auth_service.py Unit Token caching, expiry, region extraction

.NET SDK

Test fakes for WhenHandlingTransientErrors

Added fake infrastructure under WhenHandlingTransientErrors/Fakes/ to support unit testing of the HeimdallApiHttpClient when transient errors occur:

File Description
FakeHttpMessageHandler.cs Returns a fixed response or a sequence of responses, mirroring the one in WhenHandlingErrorResponses
HeimdallApiHttpClientFactory.cs Factory that wires up HeimdallApiHttpClient with the fake handler and a no-op delay for instant tests
StubAccessTokenProvider.cs Stub IAccessTokenProvider returning a static token

These follow the same pattern as the existing WhenHandlingErrorResponses/Fakes/ test infrastructure.

@joakimia
joakimia force-pushed the chore/add-integration-tests branch from 1a5ec33 to fae1c21 Compare July 22, 2026 10:34
@joakimia
joakimia marked this pull request as ready for review July 22, 2026 10:38
@joakimia
joakimia requested a review from a team as a code owner July 22, 2026 10:38
mHjertaker added a commit that referenced this pull request Aug 5, 2026
## Summary

Extracted from #132. Wires grid_insights and capacity_monitoring
endpoints that already existed in the generated API clients through
`HeimdallApiClient`, and fixes what surfaced when those wrappers were
first exercised against the API.

**New endpoint wrappers**

- Historical: `get_currents`, `get_conductor_temperatures`, `get_icing`,
`get_sag_and_clearance`, `get_apparent_power`, `get_heimdall_dlrs`,
`get_heimdall_aars`, `get_circuit_ratings`
- Latest: `get_latest_apparent_power`, `get_icing_forecast`

**Fixes**

- `get_currents` raised `ImportError` at call time — the client method
imported a wrapper that was never written. The import is function-local,
so linting and package import stayed green.
- Windowed endpoints returned 400: timestamps must be Z-suffixed UTC,
but `datetime.isoformat()` always emits a `+00:00` offset. Normalized
via `as_zulu()` in `_timestamps.py`, applied in the hand-written
wrappers so regeneration cannot overwrite it. Naive input is treated as
UTC; other offsets are converted.
- Forwarded parameters the wrappers dropped: `unit_system` on
`get_conductor_temperatures`, `quantity` on the three rating endpoints,
and `since` on the latest endpoints that accept it.

**Generator**

`openapi-python-client` formats its output via post-hooks that call the
bare `ruff` executable, which silently no-ops when ruff is not on `PATH`
— leaving generated code unformatted and turning a 3-file change into a
54-file diff. The hooks now run through `python -m ruff`, and
unformatted output fails `generate-module-client.ps1` rather than
reaching a commit. Both modules are regenerated with that in place.

**Tests**

- `tests/integration/` — windowed and latest endpoints in separate
files, covering `unit_system`, `quantity`, `since`, timestamp
normalization across naive / UTC / offset input, and the 30-day window
cap. Endpoints skip rather than fail on 404 so an asset without data for
a metric cannot mask a wiring bug.
- `tests/unit/` — resolves every lazily-imported wrapper and covers
`as_zulu`. These run on pull requests, where the integration suite does
not.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Marius Hjertaker <marius.hjertaker@heimdallpower.com>
@mHjertaker mHjertaker closed this Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants