Files
Brian Bjarke Jensen 1676fd10c9
Python Code Quality / python-code-quality (push) Successful in 15s
Test Python Package / test (push) Failing after 16s
initial commit
2025-10-30 00:00:02 +01:00

230 lines
7.5 KiB
Python

"""Unit tests for the HourData DTO model."""
from datetime import datetime
from zoneinfo import ZoneInfo
import unittest
import pytest
from pydantic import ValidationError
from elprisenligenu.dto.hour_data import HourData
class TestHourData(unittest.TestCase):
"""Test cases for the HourData model."""
def test_valid_hour_data_creation(self) -> None:
"""Test creating a valid HourData instance."""
# Arrange
tz = ZoneInfo("Europe/Copenhagen")
start_time = datetime(2024, 10, 29, 12, 0, 0, tzinfo=tz)
end_time = datetime(2024, 10, 29, 13, 0, 0, tzinfo=tz)
# Act
hour_data = HourData(
DKK_per_kWh=1.2345,
EUR_per_kWh=0.1659,
EXR=7.4371,
time_start=start_time,
time_end=end_time,
)
# Assert
self.assertEqual(hour_data.DKK_per_kWh, 1.2345)
self.assertEqual(hour_data.EUR_per_kWh, 0.1659)
self.assertEqual(hour_data.EXR, 7.4371)
self.assertEqual(hour_data.time_start, start_time)
self.assertEqual(hour_data.time_end, end_time)
def test_hour_data_from_api_response(self) -> None:
"""Test creating HourData from typical API response data."""
# Act - Pydantic can parse ISO datetime strings
hour_data = HourData(
DKK_per_kWh=1.3929,
EUR_per_kWh=0.18729,
EXR=7.437118,
time_start=datetime.fromisoformat("2022-11-25T00:00:00+01:00"),
time_end=datetime.fromisoformat("2022-11-25T01:00:00+01:00"),
)
# Assert
self.assertEqual(hour_data.DKK_per_kWh, 1.3929)
self.assertEqual(hour_data.EUR_per_kWh, 0.18729)
self.assertEqual(hour_data.EXR, 7.437118)
self.assertEqual(hour_data.time_start.year, 2022)
self.assertEqual(hour_data.time_start.month, 11)
self.assertEqual(hour_data.time_start.day, 25)
self.assertEqual(hour_data.time_start.hour, 0)
self.assertEqual(hour_data.time_end.hour, 1)
def test_hour_data_validation_missing_fields(self) -> None:
"""Test validation fails when required fields are missing."""
# Arrange
incomplete_data = {
"DKK_per_kWh": 1.2345,
"EUR_per_kWh": 0.1659,
# Missing EXR, time_start, time_end
}
# Act & Assert
with pytest.raises(ValidationError) as exc_info:
HourData(**incomplete_data) # type: ignore[arg-type]
errors = exc_info.value.errors()
missing_fields = {error["loc"][0] for error in errors}
self.assertIn("EXR", missing_fields)
self.assertIn("time_start", missing_fields)
self.assertIn("time_end", missing_fields)
def test_hour_data_validation_invalid_types(self) -> None:
"""Test validation fails with invalid data types."""
# Arrange
invalid_data = {
"DKK_per_kWh": "not_a_number", # Should be float
"EUR_per_kWh": 0.1659,
"EXR": 7.4371,
"time_start": "2024-10-29T12:00:00+01:00",
"time_end": "2024-10-29T13:00:00+01:00",
}
# Act & Assert
with pytest.raises(ValidationError) as exc_info:
HourData(**invalid_data) # type: ignore[arg-type]
errors = exc_info.value.errors()
self.assertTrue(any(error["loc"][0] == "DKK_per_kWh" for error in errors))
def test_hour_data_negative_prices(self) -> None:
"""Test HourData accepts negative prices (real markets)."""
# Arrange
tz = ZoneInfo("Europe/Copenhagen")
# Act
hour_data = HourData(
DKK_per_kWh=-0.5, # Negative price
EUR_per_kWh=-0.067,
EXR=7.4371,
time_start=datetime(2024, 10, 29, 12, 0, 0, tzinfo=tz),
time_end=datetime(2024, 10, 29, 13, 0, 0, tzinfo=tz),
)
# Assert
self.assertEqual(hour_data.DKK_per_kWh, -0.5)
self.assertEqual(hour_data.EUR_per_kWh, -0.067)
def test_hour_data_zero_prices(self) -> None:
"""Test HourData accepts zero prices."""
# Arrange
tz = ZoneInfo("Europe/Copenhagen")
# Act
hour_data = HourData(
DKK_per_kWh=0.0,
EUR_per_kWh=0.0,
EXR=7.4371,
time_start=datetime(2024, 10, 29, 12, 0, 0, tzinfo=tz),
time_end=datetime(2024, 10, 29, 13, 0, 0, tzinfo=tz),
)
# Assert
self.assertEqual(hour_data.DKK_per_kWh, 0.0)
self.assertEqual(hour_data.EUR_per_kWh, 0.0)
def test_hour_data_serialization(self) -> None:
"""Test HourData can be serialized to JSON."""
# Arrange
tz = ZoneInfo("Europe/Copenhagen")
start_time = datetime(2024, 10, 29, 12, 0, 0, tzinfo=tz)
end_time = datetime(2024, 10, 29, 13, 0, 0, tzinfo=tz)
hour_data = HourData(
DKK_per_kWh=1.2345,
EUR_per_kWh=0.1659,
EXR=7.4371,
time_start=start_time,
time_end=end_time,
)
# Act
json_data = hour_data.model_dump()
# Assert
self.assertEqual(json_data["DKK_per_kWh"], 1.2345)
self.assertEqual(json_data["EUR_per_kWh"], 0.1659)
self.assertEqual(json_data["EXR"], 7.4371)
self.assertEqual(json_data["time_start"], start_time)
self.assertEqual(json_data["time_end"], end_time)
def test_hour_data_string_representation(self) -> None:
"""Test HourData string representation is readable."""
# Arrange
tz = ZoneInfo("Europe/Copenhagen")
hour_data = HourData(
DKK_per_kWh=1.2345,
EUR_per_kWh=0.1659,
EXR=7.4371,
time_start=datetime(2024, 10, 29, 12, 0, 0, tzinfo=tz),
time_end=datetime(2024, 10, 29, 13, 0, 0, tzinfo=tz),
)
# Act
str_repr = str(hour_data)
# Assert
self.assertIn("DKK_per_kWh=1.2345", str_repr)
self.assertIn("EUR_per_kWh=0.1659", str_repr)
self.assertIn("EXR=7.4371", str_repr)
def test_hour_data_equality(self) -> None:
"""Test HourData equality comparison."""
# Arrange
tz = ZoneInfo("Europe/Copenhagen")
start_time = datetime(2024, 10, 29, 12, 0, 0, tzinfo=tz)
end_time = datetime(2024, 10, 29, 13, 0, 0, tzinfo=tz)
hour_data1 = HourData(
DKK_per_kWh=1.2345,
EUR_per_kWh=0.1659,
EXR=7.4371,
time_start=start_time,
time_end=end_time,
)
hour_data2 = HourData(
DKK_per_kWh=1.2345,
EUR_per_kWh=0.1659,
EXR=7.4371,
time_start=start_time,
time_end=end_time,
)
# Act & Assert
self.assertEqual(hour_data1, hour_data2)
def test_hour_data_inequality(self) -> None:
"""Test HourData inequality comparison."""
# Arrange
tz = ZoneInfo("Europe/Copenhagen")
start_time = datetime(2024, 10, 29, 12, 0, 0, tzinfo=tz)
end_time = datetime(2024, 10, 29, 13, 0, 0, tzinfo=tz)
hour_data1 = HourData(
DKK_per_kWh=1.2345,
EUR_per_kWh=0.1659,
EXR=7.4371,
time_start=start_time,
time_end=end_time,
)
hour_data2 = HourData(
DKK_per_kWh=2.0000, # Different price
EUR_per_kWh=0.1659,
EXR=7.4371,
time_start=start_time,
time_end=end_time,
)
# Act & Assert
self.assertNotEqual(hour_data1, hour_data2)