initial commit
Python Code Quality / python-code-quality (push) Successful in 15s
Test Python Package / test (push) Failing after 16s

This commit is contained in:
Brian Bjarke Jensen
2025-10-30 00:00:02 +01:00
parent 2fd2e949bb
commit 1676fd10c9
20 changed files with 2385 additions and 12 deletions
+1
View File
@@ -0,0 +1 @@
"""Test package for elprisenligenu."""
+48
View File
@@ -0,0 +1,48 @@
"""Test configuration and fixtures for elprisenligenu tests."""
from datetime import datetime
from zoneinfo import ZoneInfo
import pytest
def pytest_configure(config: pytest.Config) -> None:
"""Configure pytest with custom markers."""
config.addinivalue_line(
"markers",
"integration: marks tests as integration tests (may require internet)",
)
@pytest.fixture
def mock_api_response() -> list[dict]:
"""Fixture providing a mock API response."""
return [
{
"DKK_per_kWh": 1.3929,
"EUR_per_kWh": 0.18729,
"EXR": 7.437118,
"time_start": "2024-10-29T00:00:00+01:00",
"time_end": "2024-10-29T01:00:00+01:00",
},
{
"DKK_per_kWh": 1.30291,
"EUR_per_kWh": 0.17519,
"EXR": 7.437118,
"time_start": "2024-10-29T01:00:00+01:00",
"time_end": "2024-10-29T02:00:00+01:00",
},
]
@pytest.fixture
def sample_hour_data() -> dict:
"""Fixture providing sample HourData for testing."""
tz = ZoneInfo("Europe/Copenhagen")
return {
"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),
}
+152
View File
@@ -0,0 +1,152 @@
"""Integration tests for the elprisenligenu module."""
from datetime import datetime
from zoneinfo import ZoneInfo
import pytest
from elprisenligenu.api import API
from elprisenligenu.dto.hour_data import HourData
class TestElprisenLigenIntegration:
"""Integration tests that make real API calls."""
def setup_method(self) -> None:
"""Set up test fixtures before each test method."""
self.api = API()
self.tz = ZoneInfo("Europe/Copenhagen")
@pytest.mark.integration
def test_get_current_prices_dk1(self) -> None:
"""Test fetching current day prices for DK1 (integration test)."""
# Act
result = self.api.get_daily_prices(zone="DK1")
# Assert
assert isinstance(result, list)
assert all(isinstance(item, HourData) for item in result)
if result: # If data is available
first_hour = result[0]
assert isinstance(first_hour.DKK_per_kWh, float)
assert isinstance(first_hour.EUR_per_kWh, float)
assert isinstance(first_hour.EXR, float)
assert isinstance(first_hour.time_start, datetime)
assert isinstance(first_hour.time_end, datetime)
# Basic sanity checks
assert first_hour.EXR > 0 # Exchange rate should be positive
assert first_hour.time_start < first_hour.time_end
@pytest.mark.integration
def test_get_current_prices_dk2(self) -> None:
"""Test fetching current day prices for DK2 (integration test)."""
# Act
result = self.api.get_daily_prices(zone="DK2")
# Assert
assert isinstance(result, list)
assert all(isinstance(item, HourData) for item in result)
if result: # If data is available
first_hour = result[0]
assert isinstance(first_hour.DKK_per_kWh, float)
assert isinstance(first_hour.EUR_per_kWh, float)
assert isinstance(first_hour.EXR, float)
assert isinstance(first_hour.time_start, datetime)
assert isinstance(first_hour.time_end, datetime)
@pytest.mark.integration
def test_get_historical_prices(self) -> None:
"""Test fetching historical prices (integration test)."""
# Arrange - Use a date that should have data (not too far back)
historical_date = datetime(2024, 10, 1, tzinfo=self.tz)
# Act
result = self.api.get_daily_prices(zone="DK1", date=historical_date)
# Assert
assert isinstance(result, list)
if result: # If historical data is available
assert len(result) <= 24 # Should be max 24 hours
assert all(isinstance(item, HourData) for item in result)
# Check that all times are from the requested date
for hour_data in result:
assert hour_data.time_start.date() == historical_date.date()
@pytest.mark.integration
def test_price_consistency(self) -> None:
"""Test that EUR and DKK prices are consistent with exchange rate."""
# Act
result = self.api.get_daily_prices(zone="DK1")
# Assert
if result:
for hour_data in result:
# Calculate expected DKK price from EUR price and exchange rate
expected_dkk = hour_data.EUR_per_kWh * hour_data.EXR
# Allow for small floating point differences
difference = abs(hour_data.DKK_per_kWh - expected_dkk)
assert difference < 0.001, (
f"Price inconsistency: DKK={hour_data.DKK_per_kWh}, "
f"EUR={hour_data.EUR_per_kWh}, EXR={hour_data.EXR}, "
f"Expected DKK={expected_dkk}"
)
@pytest.mark.integration
def test_time_ordering(self) -> None:
"""Test that hours are returned in chronological order."""
# Act
result = self.api.get_daily_prices(zone="DK1")
# Assert
if len(result) > 1:
for i in range(1, len(result)):
assert result[i - 1].time_start <= result[i].time_start, (
f"Hours not in chronological order: "
f"{result[i - 1].time_start} > {result[i].time_start}"
)
@pytest.mark.integration
def test_hour_duration(self) -> None:
"""Test that each hour period is exactly 1 hour long."""
# Act
result = self.api.get_daily_prices(zone="DK1")
# Assert
if result:
for hour_data in result:
duration = hour_data.time_end - hour_data.time_start
assert duration.total_seconds() == 3600, (
f"Hour duration is not 1 hour: {duration}"
)
@pytest.mark.integration
def test_both_zones_same_day(self) -> None:
"""Test that both zones return data for the same day."""
# Arrange
test_date = datetime(2024, 10, 15, tzinfo=self.tz)
# Act
dk1_result = self.api.get_daily_prices(zone="DK1", date=test_date)
dk2_result = self.api.get_daily_prices(zone="DK2", date=test_date)
# Assert
# Both zones should have data for the same day
if dk1_result and dk2_result:
assert len(dk1_result) == len(dk2_result)
# Times should be the same
for dk1_hour, dk2_hour in zip(dk1_result, dk2_result):
assert dk1_hour.time_start == dk2_hour.time_start
assert dk1_hour.time_end == dk2_hour.time_end
# Exchange rates should be the same
assert dk1_hour.EXR == dk2_hour.EXR
# But prices can be different between zones
# (That's the whole point of having two zones!)
+1
View File
@@ -0,0 +1 @@
"""Unit tests package for elprisenligenu."""
+321
View File
@@ -0,0 +1,321 @@
"""Unit tests for the API class."""
import json
from datetime import datetime
import unittest
from unittest.mock import Mock, patch
from zoneinfo import ZoneInfo
import pytest
import requests
from elprisenligenu.api import API
from elprisenligenu.dto.hour_data import HourData
class TestAPI(unittest.TestCase):
"""Test cases for the API class."""
api: API
tz: ZoneInfo
@classmethod
def setUpClass(cls) -> None:
"""Set up test fixtures before any tests are run."""
cls.api = API()
cls.tz = ZoneInfo("Europe/Copenhagen")
def test_api_initialization(self) -> None:
"""Test API class initialization."""
# Act
api = API()
# Assert
self.assertIsNotNone(api.session)
self.assertIsInstance(api.session, requests.Session)
self.assertIsNotNone(api.logger)
self.assertEqual(api.BASE_URL, "https://www.elprisenligenu.dk/api/v1/prices")
self.assertEqual(api.TIMEZONE, ZoneInfo("Europe/Copenhagen"))
def test_endpoint_construction_dk1(self) -> None:
"""Test endpoint URL construction for DK1."""
# Arrange
date = datetime(2024, 10, 29, 12, 0, 0, tzinfo=self.tz)
# Act
endpoint = API._endpoint(date, "DK1")
# Assert
expected = "https://www.elprisenligenu.dk/api/v1/prices/2024/10-29_DK1.json"
self.assertEqual(endpoint, expected)
def test_endpoint_construction_dk2(self) -> None:
"""Test endpoint URL construction for DK2."""
# Arrange
date = datetime(2024, 1, 5, 12, 0, 0, tzinfo=self.tz)
# Act
endpoint = API._endpoint(date, "DK2")
# Assert
expected = "https://www.elprisenligenu.dk/api/v1/prices/2024/01-05_DK2.json"
self.assertEqual(endpoint, expected)
def test_endpoint_construction_edge_dates(self) -> None:
"""Test endpoint URL construction for edge case dates."""
# Test December 31st
date = datetime(2023, 12, 31, 12, 0, 0, tzinfo=self.tz)
endpoint = API._endpoint(date, "DK1")
expected = "https://www.elprisenligenu.dk/api/v1/prices/2023/12-31_DK1.json"
self.assertEqual(endpoint, expected)
# Test January 1st
date = datetime(2024, 1, 1, 12, 0, 0, tzinfo=self.tz)
endpoint = API._endpoint(date, "DK2")
expected = "https://www.elprisenligenu.dk/api/v1/prices/2024/01-01_DK2.json"
self.assertEqual(endpoint, expected)
@patch("elprisenligenu.api.requests.Session.get")
def test_get_daily_prices_success_dk1(self, mock_get: Mock) -> None:
"""Test successful API call for DK1."""
# Arrange
mock_response_data = [
{
"DKK_per_kWh": 1.3929,
"EUR_per_kWh": 0.18729,
"EXR": 7.437118,
"time_start": "2024-10-29T00:00:00+01:00",
"time_end": "2024-10-29T01:00:00+01:00",
},
{
"DKK_per_kWh": 1.30291,
"EUR_per_kWh": 0.17519,
"EXR": 7.437118,
"time_start": "2024-10-29T01:00:00+01:00",
"time_end": "2024-10-29T02:00:00+01:00",
},
]
mock_response = Mock()
mock_response.json.return_value = mock_response_data
mock_response.raise_for_status.return_value = None
mock_get.return_value = mock_response
date = datetime(2024, 10, 29, 12, 0, 0, tzinfo=self.tz)
# Act
result = self.api.get_daily_prices(zone="DK1", date=date)
# Assert
self.assertEqual(len(result), 2)
self.assertTrue(all(isinstance(item, HourData) for item in result))
self.assertAlmostEqual(result[0].DKK_per_kWh, 1.3929, places=4)
self.assertAlmostEqual(result[1].DKK_per_kWh, 1.30291, places=4)
# Verify API was called correctly
expected_url = "https://www.elprisenligenu.dk/api/v1/prices/2024/10-29_DK1.json"
mock_get.assert_called_once_with(expected_url)
@patch("elprisenligenu.api.requests.Session.get")
def test_get_daily_prices_success_dk2(self, mock_get: Mock) -> None:
"""Test successful API call for DK2."""
# Arrange
mock_response_data = [
{
"DKK_per_kWh": 1.5000,
"EUR_per_kWh": 0.2000,
"EXR": 7.5,
"time_start": "2024-10-29T00:00:00+01:00",
"time_end": "2024-10-29T01:00:00+01:00",
}
]
mock_response = Mock()
mock_response.json.return_value = mock_response_data
mock_response.raise_for_status.return_value = None
mock_get.return_value = mock_response
date = datetime(2024, 10, 29, 12, 0, 0, tzinfo=self.tz)
# Act
result = self.api.get_daily_prices(zone="DK2", date=date)
# Assert
self.assertEqual(len(result), 1)
self.assertAlmostEqual(result[0].DKK_per_kWh, 1.5000, places=4)
# Verify API was called correctly
expected_url = "https://www.elprisenligenu.dk/api/v1/prices/2024/10-29_DK2.json"
mock_get.assert_called_once_with(expected_url)
def test_get_daily_prices_invalid_zone(self) -> None:
"""Test validation error for invalid zone."""
# Arrange
date = datetime(2024, 10, 29, 12, 0, 0, tzinfo=self.tz)
# Act & Assert
with pytest.raises(ValueError, match="zone must be either 'DK1' or 'DK2'"):
self.api.get_daily_prices(zone="DK3", date=date) # type: ignore
def test_get_daily_prices_invalid_date_type(self) -> None:
"""Test validation error for invalid date type."""
# Act & Assert
with pytest.raises(TypeError, match="date must be a datetime object"):
self.api.get_daily_prices(zone="DK1", date="2024-10-29") # type: ignore
def test_get_daily_prices_naive_datetime(self) -> None:
"""Test validation error for naive datetime."""
# Arrange
naive_date = datetime(2024, 10, 29, 12, 0, 0) # No timezone
# Act & Assert
with pytest.raises(ValueError, match="date must be timezone-aware"):
self.api.get_daily_prices(zone="DK1", date=naive_date)
@patch("elprisenligenu.api.requests.Session.get")
def test_get_daily_prices_timezone_conversion(self, mock_get: Mock) -> None:
"""Test automatic timezone conversion."""
# Arrange
mock_response_data = [
{
"DKK_per_kWh": 1.0,
"EUR_per_kWh": 0.13,
"EXR": 7.5,
"time_start": "2024-10-29T00:00:00+01:00",
"time_end": "2024-10-29T01:00:00+01:00",
}
]
mock_response = Mock()
mock_response.json.return_value = mock_response_data
mock_response.raise_for_status.return_value = None
mock_get.return_value = mock_response
# Use UTC timezone instead of Copenhagen
utc_date = datetime(2024, 10, 29, 11, 0, 0, tzinfo=ZoneInfo("UTC"))
# Act
result = self.api.get_daily_prices(zone="DK1", date=utc_date)
# Assert
self.assertEqual(len(result), 1)
# Should still work, date gets converted internally
@patch("elprisenligenu.api.requests.Session.get")
def test_get_daily_prices_http_error(self, mock_get: Mock) -> None:
"""Test handling of HTTP errors."""
# Arrange
mock_response = Mock()
mock_response.raise_for_status.side_effect = requests.HTTPError("404 Not Found")
mock_get.return_value = mock_response
date = datetime(2024, 10, 29, 12, 0, 0, tzinfo=self.tz)
# Act & Assert
with pytest.raises(requests.HTTPError):
self.api.get_daily_prices(zone="DK1", date=date)
@patch("elprisenligenu.api.requests.Session.get")
def test_get_daily_prices_invalid_json(self, mock_get: Mock) -> None:
"""Test handling of invalid JSON response."""
# Arrange
mock_response = Mock()
mock_response.raise_for_status.return_value = None
mock_response.json.side_effect = json.JSONDecodeError("Invalid JSON", "", 0)
mock_get.return_value = mock_response
date = datetime(2024, 10, 29, 12, 0, 0, tzinfo=self.tz)
# Act & Assert
with pytest.raises(json.JSONDecodeError):
self.api.get_daily_prices(zone="DK1", date=date)
@patch("elprisenligenu.api.requests.Session.get")
def test_get_daily_prices_empty_response(self, mock_get: Mock) -> None:
"""Test handling of empty response."""
# Arrange
mock_response = Mock()
mock_response.json.return_value = []
mock_response.raise_for_status.return_value = None
mock_get.return_value = mock_response
date = datetime(2024, 10, 29, 12, 0, 0, tzinfo=self.tz)
# Act
result = self.api.get_daily_prices(zone="DK1", date=date)
# Assert
self.assertEqual(result, [])
@patch("elprisenligenu.api.requests.Session.get")
def test_get_daily_prices_malformed_data(self, mock_get: Mock) -> None:
"""Test handling of malformed response data."""
# Arrange
mock_response_data = [
{
"DKK_per_kWh": "not_a_number", # Invalid type
"EUR_per_kWh": 0.18729,
"EXR": 7.437118,
"time_start": "2024-10-29T00:00:00+01:00",
"time_end": "2024-10-29T01:00:00+01:00",
}
]
mock_response = Mock()
mock_response.json.return_value = mock_response_data
mock_response.raise_for_status.return_value = None
mock_get.return_value = mock_response
date = datetime(2024, 10, 29, 12, 0, 0, tzinfo=self.tz)
# Act & Assert
with pytest.raises(Exception): # Pydantic validation error
self.api.get_daily_prices(zone="DK1", date=date)
def test_get_daily_prices_default_parameters(self) -> None:
"""Test that default parameters work correctly."""
# This test verifies the method signature but doesn't make real API calls
# We just check that the method can be called without parameters
# Act & Assert - should not raise an error for the method signature
try:
# We expect this to fail with a network error in tests, but the
# parameter validation should pass
self.api.get_daily_prices()
except (requests.RequestException, requests.ConnectionError):
# Expected in test environment without internet
pass
@patch("elprisenligenu.api.requests.Session.get")
def test_get_daily_prices_full_day_data(self, mock_get: Mock) -> None:
"""Test processing a full day of 24 hours."""
# Arrange - Create 24 hours of mock data
mock_response_data = []
for hour in range(24):
mock_response_data.append(
{
"DKK_per_kWh": 1.0 + hour * 0.1,
"EUR_per_kWh": 0.13 + hour * 0.01,
"EXR": 7.5,
"time_start": f"2024-10-29T{hour:02d}:00:00+01:00",
"time_end": f"2024-10-29T{(hour + 1) % 24:02d}:00:00+01:00",
}
)
mock_response = Mock()
mock_response.json.return_value = mock_response_data
mock_response.raise_for_status.return_value = None
mock_get.return_value = mock_response
date = datetime(2024, 10, 29, 12, 0, 0, tzinfo=self.tz)
# Act
result = self.api.get_daily_prices(zone="DK1", date=date)
# Assert
self.assertEqual(len(result), 24)
self.assertTrue(all(isinstance(item, HourData) for item in result))
# Check that prices increase as expected
self.assertEqual(result[0].DKK_per_kWh, 1.0)
self.assertAlmostEqual(result[23].DKK_per_kWh, 3.3, 3) # 1.0 + 23 * 0.1
+229
View File
@@ -0,0 +1,229 @@
"""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)