Skip to content

Commit

Permalink
update test, remove try and except
Browse files Browse the repository at this point in the history
  • Loading branch information
peterdudfield committed Jul 31, 2024
1 parent 45431fa commit edf4107
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 98 deletions.
78 changes: 37 additions & 41 deletions src/national.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
# Initialize Elexon API client
api_client = ApiClient()
forecast_api = GenerationForecastApi(api_client)
forecast_generation_wind_and_solar_day_ahead_get = forecast_api.forecast_generation_wind_and_solar_day_ahead_get


@router.get("/elexon", summary="Get elexon Solar Forecast")
Expand All @@ -67,50 +68,45 @@ def get_elexon_forecast(
Returns:
SolarForecastResponse: The forecast data wrapped in a SolarForecastResponse model.
"""
try:
response = forecast_api.forecast_generation_wind_and_solar_day_ahead_get(
_from=start_datetime_utc.isoformat(),
to=end_datetime_utc.isoformat(),
process_type=process_type,
format="json",
)

if not response.data:
return SolarForecastResponse(data=[])

df = pd.DataFrame([item.to_dict() for item in response.data])
logger.debug("DataFrame Columns: %s", df.columns)
logger.debug("DataFrame Sample: %s", df.head())

# Filter to include only solar forecasts
solar_df = df[df["business_type"] == "Solar generation"]
logger.debug("Filtered Solar DataFrame: %s", solar_df.head())

forecast_values = []
for _, row in solar_df.iterrows():
try:
forecast_values.append(
SolarForecastValue(
timestamp=pd.to_datetime(row["publish_time"]).to_pydatetime(),
expected_power_generation_megawatts=row.get("quantity"),
plevels=None,
)
)
except KeyError as e:
logger.error("KeyError: %s. Data: %s", str(e), row)
raise HTTPException(status_code=500, detail="Internal Server Error")
except Exception as e:
logger.error(
"Error during DataFrame to Model conversion: %s. Data: %s", str(e), row
)
raise HTTPException(status_code=500, detail="Internal Server Error")
response = forecast_generation_wind_and_solar_day_ahead_get(
_from=start_datetime_utc.isoformat(),
to=end_datetime_utc.isoformat(),
process_type=process_type,
format="json",
)

if not response.data:
return SolarForecastResponse(data=[])

result = SolarForecastResponse(data=forecast_values)
return result
df = pd.DataFrame([item.to_dict() for item in response.data])
logger.debug("DataFrame Columns: %s", df.columns)
logger.debug("DataFrame Sample: %s", df.head())

# Filter to include only solar forecasts
solar_df = df[df["business_type"] == "Solar generation"]
logger.debug("Filtered Solar DataFrame: %s", solar_df.head())

forecast_values = []
for _, row in solar_df.iterrows():
try:
forecast_values.append(
SolarForecastValue(
timestamp=pd.to_datetime(row["publish_time"]).to_pydatetime(),
expected_power_generation_megawatts=row.get("quantity"),
)
)
except KeyError as e:
logger.error("KeyError: %s. Data: %s", str(e), row)
raise HTTPException(status_code=500, detail="Internal Server Error")
except Exception as e:
logger.error(
"Error during DataFrame to Model conversion: %s. Data: %s", str(e), row
)
raise HTTPException(status_code=500, detail="Internal Server Error")

except Exception as e:
logger.error("Unhandled exception: %s", str(e))
raise HTTPException(status_code=500, detail="Internal Server Error")
result = SolarForecastResponse(data=forecast_values)
return result


@router.get(
Expand Down
112 changes: 55 additions & 57 deletions src/tests/test_elexon_forecast.py
Original file line number Diff line number Diff line change
@@ -1,61 +1,59 @@
import pytest
import requests
import requests_mock
from unittest.mock import patch

import pandas as pd

from pydantic_models import BaseModel
from typing import Optional

# InsightsApiModelsResponsesResponseWithMetadata1InsightsApiModelsResponsesTransparencyDayAheadGenerationForWindAndSolar

API_URL = "/v0/solar/GB/national/elexon"


@pytest.fixture
def mock_data():
return {
"data": [
{
"timestamp": "2024-07-24T16:45:09+00:00",
"expected_power_generation_megawatts": 0,
"plevels": None,
},
{
"timestamp": "2024-07-24T16:45:09+00:00",
"expected_power_generation_megawatts": 0,
"plevels": None,
},
]
}


def test_get_elexon_forecast_with_data(mock_data, api_client):
with requests_mock.Mocker() as m:
url = (
f"https://data.elexon.co.uk/bmrs/api/v1/forecast/generation/wind-and-solar/day-ahead"
)
m.get(url, json=mock_data, headers={"Content-Type": "application/json"})

response = api_client.get('/v0/solar/GB/national/elexon')
print("Response Headers:", response.headers)
# Assertions
assert response.status_code == 200
assert response.headers.get("Content-Type") == "application/json"
assert response.json() == mock_data


@pytest.fixture
def empty_mock_data():
return {"data": []}


def test_get_elexon_forecast_no_data(empty_mock_data):
with requests_mock.Mocker() as m:
url = (
f"{API_URL}?start_datetime_utc=2024-07-22T10:56:59.194610"
f"&end_datetime_utc=2024-07-28T10:56:59.194680"
f"&process_type=Day Ahead"
)

m.get(url, json=empty_mock_data, headers={"Content-Type": "application/json"})

response = requests.get(url)
print("Response Headers:", response.headers)
# Assertions
assert response.status_code == 200
assert response.headers.get("Content-Type") == "application/json"
assert response.json() == empty_mock_data
class MockClass(BaseModel):

publish_time: str
quantity: float
business_type: Optional[str] = "Solar generation"

def to_dict(self):
return self.__dict__


mock_data = [
MockClass(
**{
"publish_time": "2024-07-24T16:45:09+00:00",
"quantity": 0,
}
),
MockClass(
**{
"publish_time": "2024-07-24T16:45:09+00:00",
"quantity": 0,
}
),
]


class MockResponse:
def __init__(self):
self.data = mock_data


@patch("national.forecast_generation_wind_and_solar_day_ahead_get")
def test_get_elexon_forecast_with_data(mock_function, api_client):
mock_function.return_value = MockResponse()

response = api_client.get("/v0/solar/GB/national/elexon")
print("Response Headers:", response.headers)
# Assertions
assert response.status_code == 200
assert response.headers.get("Content-Type") == "application/json"

api_data = response.json()["data"]
assert len(api_data) == len(mock_data)
for i in range(len(api_data)):
assert api_data[i]["expected_power_generation_megawatts"] == mock_data[i].quantity
assert pd.Timestamp(api_data[i]["timestamp"]) == pd.Timestamp(mock_data[i].publish_time)

0 comments on commit edf4107

Please sign in to comment.