mirror of
https://github.com/aclist/dztui.git
synced 2026-10-30 22:52:42 +01:00
chore: add calculator reference test
This commit is contained in:
1 parent
0e58cf514e
commit
f07a2dea5f
2 files changed
+111
No files matched your search
@@ -47,6 +47,7 @@ docs = [
|
|||||||
]
|
]
|
||||||
test = [
|
test = [
|
||||||
"black==25.1.0",
|
"black==25.1.0",
|
||||||
|
"hypothesis==6.167.1",
|
||||||
"pre-commit==4.4.0",
|
"pre-commit==4.4.0",
|
||||||
"pytest==8.4.2",
|
"pytest==8.4.2",
|
||||||
"pytest-cov==7.0.0",
|
"pytest-cov==7.0.0",
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from hypothesis import given, strategies as st
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
from dzgui.views.dialogs.calc import (
|
||||||
|
LocalClock,
|
||||||
|
ServerClock,
|
||||||
|
Time,
|
||||||
|
TimePicker,
|
||||||
|
DAY_START_TIME,
|
||||||
|
DAY_END_TIME,
|
||||||
|
)
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.FOO
|
||||||
|
|
||||||
|
|
||||||
|
class DummyEmitter:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(params=[("05:00", 10.0), ("15:30", 5.0)])
|
||||||
|
def accel_server_clock(request) -> None:
|
||||||
|
clock_time, expect = request.param
|
||||||
|
cur_time = Time(clock_time, 5.0, 2.0)
|
||||||
|
emitter = DummyEmitter()
|
||||||
|
local_clock = LocalClock(emitter)
|
||||||
|
server_clock = ServerClock(cur_time, emitter, local_clock)
|
||||||
|
return expect, server_clock
|
||||||
|
|
||||||
|
|
||||||
|
def test_accel_factor(accel_server_clock) -> None:
|
||||||
|
"""Static test checking times at known boundaries"""
|
||||||
|
expect, clock = accel_server_clock
|
||||||
|
assert clock.get_accel_factor(clock.cur_time) == expect
|
||||||
|
|
||||||
|
|
||||||
|
def reference_calc(start, end, day_factor, night_factor):
|
||||||
|
"""
|
||||||
|
Reference implementation to test validity of UI-side calculator
|
||||||
|
Aggregates total seconds and applies accel factors after
|
||||||
|
"""
|
||||||
|
day_start = datetime.combine(start.date(), DAY_START_TIME)
|
||||||
|
day_end = datetime.combine(start.date(), DAY_END_TIME)
|
||||||
|
night_factor = day_factor * night_factor
|
||||||
|
|
||||||
|
if end < start:
|
||||||
|
end += timedelta(days=1)
|
||||||
|
|
||||||
|
day_max = max(start, day_start)
|
||||||
|
day_min = min(end, day_end)
|
||||||
|
|
||||||
|
next_day_start = datetime.combine(end.date(), DAY_START_TIME)
|
||||||
|
next_day_end = datetime.combine(end.date(), DAY_END_TIME)
|
||||||
|
|
||||||
|
range1 = (day_end - day_max).total_seconds()
|
||||||
|
range2 = (min(end, next_day_end) - next_day_start).total_seconds()
|
||||||
|
|
||||||
|
if end.date() > start.date():
|
||||||
|
day_seconds = max(0, range1) + max(0, range2)
|
||||||
|
else:
|
||||||
|
day_seconds = max(0, (day_min - day_max).total_seconds())
|
||||||
|
|
||||||
|
total_seconds = (end - start).total_seconds()
|
||||||
|
night_seconds = (total_seconds - day_seconds) / night_factor
|
||||||
|
day_seconds = day_seconds / day_factor
|
||||||
|
total = night_seconds + day_seconds
|
||||||
|
|
||||||
|
return timedelta(seconds=total)
|
||||||
|
|
||||||
|
|
||||||
|
day_accel = st.floats(
|
||||||
|
min_value=1.0, max_value=24.0, allow_nan=False, allow_infinity=False
|
||||||
|
)
|
||||||
|
night_accel = st.floats(
|
||||||
|
min_value=1.0, max_value=64.0, allow_nan=False, allow_infinity=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@st.composite
|
||||||
|
def time_ranges(draw):
|
||||||
|
start_time = draw(st.times())
|
||||||
|
deltas = st.timedeltas(min_value=timedelta(0), max_value=timedelta(days=1))
|
||||||
|
duration = draw(deltas)
|
||||||
|
|
||||||
|
start = datetime.combine(datetime.now(), start_time)
|
||||||
|
end = start + duration
|
||||||
|
return start, end
|
||||||
|
|
||||||
|
|
||||||
|
@given(span=time_ranges(), day_factor=day_accel, night_factor=night_accel)
|
||||||
|
def test_time_aggregation(span, day_factor, night_factor) -> None:
|
||||||
|
start, end = span
|
||||||
|
|
||||||
|
strtime = start.strftime("%H:%M")
|
||||||
|
t = Time(strtime, day_factor, night_factor)
|
||||||
|
emitter = DummyEmitter()
|
||||||
|
local_clock = LocalClock(emitter)
|
||||||
|
server_clock = ServerClock(t, emitter, local_clock)
|
||||||
|
h = end.time().hour
|
||||||
|
m = end.time().minute
|
||||||
|
picker = TimePicker(h, m)
|
||||||
|
|
||||||
|
# NOTE: truncates microseconds to mimic widget HH:MM selection behavior
|
||||||
|
start = server_clock.get_datetime()
|
||||||
|
end = picker.get_time()
|
||||||
|
actual = server_clock.calc_delta(end)
|
||||||
|
expect = reference_calc(start, end, day_factor, night_factor)
|
||||||
|
|
||||||
|
assert actual == expect
|
||||||
Reference in new issue
Block a user