EOS/tests/test_datetimeutil.py
Bobby Noelte b630625a4d Add test to PVForecast (#174)
* Add documentation to class_pv_forecast.py.

Added documentation. Beware mostly generated by ChatGPT.

Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>

* Add CacheFileStore, datetime and logger utilities.

The `CacheFileStore` class is a singleton-based, thread-safe key-value store for managing
temporary file objects, allowing the creation, retrieval, and management of cache files.

The utility modules offer a flexible logging setup (`get_logger`) and utilities to handle
different date-time formats (`to_datetime`, `to_timestamp`) and timezone detection
(`to_timezone).

- Cache files are automatically valid for the the current date unless specified otherwise.
  This is to mimic the current behaviour used in several classes.
- The logger supports rotating log files to prevent excessive log file size.
- The `to_datetime` and `to_timestamp`functions support a wide variety of input types and formats.
  They provide the time conversion that is e.g. used in PVForecast.

Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>

* Improve testability of PVForecast

Improvements for testing of PVForecast
- Use common utility functions to allow for general testing at one spot.
  - to_datetime
  - CacheFileStore
- Use logging instead of print to easily capture in testing.
- Add validation of the json schema for Akkudoktor PV forecast data.
- Allow to create an empty PVForecast instance as base instance for testing.
- Make process_data() complete for filling a PVForecast instance for testing.
- Normalize forecast datetime to timezone of system given in loaded data.
- Do not print report but provide report for test checks.
- Get rid of cache file path using the CachFileStore to automate cache file usage.
- Improved module documentation.

Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>

* Add test for PVForecast and newly extracted utility modules.

- Add test for PVForecast
- Add test for CacheFileStore in the new cachefilestore module
- Add test for to_datetime, to_timestamp, to_timezone in the new
  datetimeutil module
- Add test for get_logger in the new logutil module

Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>

---------

Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>
Co-authored-by: Normann <github@koldrack.com>
2024-11-10 23:49:10 +01:00

120 lines
3.9 KiB
Python

"""Test Module for datetimeutil Module."""
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
import pytest
from akkudoktoreos.datetimeutil import to_datetime, to_timedelta, to_timezone
# -----------------------------
# to_datetime
# -----------------------------
# Test cases for valid timedelta inputs
@pytest.mark.parametrize(
"date_input, as_string, to_timezone, to_naiv, to_maxtime, expected_output",
[
# as datetime object
(
"2024-10-07T10:20:30.000+02:00",
None,
"Europe/Berlin",
None,
None,
datetime(2024, 10, 7, 10, 20, 30, 0, tzinfo=ZoneInfo("Europe/Berlin")),
),
(
"2024-10-07T10:20:30.000+02:00",
None,
"Europe/Berlin",
False,
None,
datetime(2024, 10, 7, 10, 20, 30, 0, tzinfo=ZoneInfo("Europe/Berlin")),
),
(
"2024-10-07T10:20:30.000+02:00",
None,
"Europe/Berlin",
True,
None,
datetime(2024, 10, 7, 10, 20, 30, 0),
),
# as string
("2024-10-07T10:20:30.000+02:00", "UTC", None, None, None, "2024-10-07T08:20:30+00:00"),
("2024-10-07T10:20:30.000+02:00", "utc", None, None, None, "2024-10-07T08:20:30+00:00"),
],
)
def test_to_datetime(date_input, as_string, to_timezone, to_naiv, to_maxtime, expected_output):
"""Test datetime conversion with valid inputs."""
assert (
to_datetime(
date_input,
as_string=as_string,
to_timezone=to_timezone,
to_naiv=to_naiv,
to_maxtime=to_maxtime,
)
== expected_output
)
# -----------------------------
# to_timedelta
# -----------------------------
# Test cases for valid timedelta inputs
@pytest.mark.parametrize(
"input_value, expected_output",
[
# timedelta input
(timedelta(days=1), timedelta(days=1)),
# String input
("2 days", timedelta(days=2)),
("5 hours", timedelta(hours=5)),
("30 minutes", timedelta(minutes=30)),
("45 seconds", timedelta(seconds=45)),
("1 day 2 hours 30 minutes 15 seconds", timedelta(days=1, hours=2, minutes=30, seconds=15)),
("3 days 4 hours", timedelta(days=3, hours=4)),
# Integer/Float input
(3600, timedelta(seconds=3600)), # 1 hour
(86400, timedelta(days=1)), # 1 day
(1800.5, timedelta(seconds=1800.5)), # 30 minutes and 0.5 seconds
# Tuple/List input
((1, 2, 30, 15), timedelta(days=1, hours=2, minutes=30, seconds=15)),
([0, 10, 0, 0], timedelta(hours=10)),
],
)
def test_to_timedelta_valid(input_value, expected_output):
"""Test to_timedelta with valid inputs."""
assert to_timedelta(input_value) == expected_output
# -----------------------------
# to_timezone
# -----------------------------
def test_to_timezone_string():
"""Test to_timezone function returns correct timezone as a string."""
lat, lon = 40.7128, -74.0060 # New York City coordinates
result = to_timezone(lat, lon, as_string=True)
assert result == "America/New_York", "Expected timezone string 'America/New_York'"
def test_to_timezone_zoneinfo():
"""Test to_timezone function returns correct timezone as a ZoneInfo object."""
lat, lon = 40.7128, -74.0060 # New York City coordinates
result = to_timezone(lat, lon)
assert isinstance(result, ZoneInfo), "Expected a ZoneInfo object"
assert result.key == "America/New_York", "Expected ZoneInfo key 'America/New_York'"
def test_to_timezone_invalid_coordinates():
"""Test to_timezone function handles invalid coordinates gracefully."""
lat, lon = 100.0, 200.0 # Invalid coordinates outside Earth range
with pytest.raises(ValueError, match="Invalid location"):
to_timezone(lat, lon, as_string=True)