File size: 2,061 Bytes
90b4eb9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | """Tests for the text rendering layer (render.py).
The critical one is `test_no_none_leaks_*`: if a missing value ever renders as
the literal "None", it silently poisons the model's prompt.
"""
from datetime import date, timedelta
from rate_my_run.models import WeekStats, TrainingSummary
from rate_my_run.render import format_pace, summary_to_text
def _empty_weeks(n=8):
"""n empty weekly buckets (oldest -> newest)."""
return [WeekStats(date.today() - timedelta(days=7 * (n - i)), 0, 0.0, 0.0, None)
for i in range(n)]
def _summary(weeks, days_since=1, mileage=None, trend="insufficient_data", signals=None):
return TrainingSummary(
weeks=weeks,
days_since_last_run=days_since,
mileage_change_pct=mileage,
pace_trend=trend,
signals=signals or [],
)
# --- format_pace ------------------------------------------------------------
def test_format_pace_basic():
assert format_pace(5.0) == "5:00/km"
assert format_pace(5.5) == "5:30/km"
def test_format_pace_none():
assert format_pace(None) == "n/a"
def test_format_pace_rounds_60s_up():
# 5.999 min would round to 5:60 -> must become 6:00
assert format_pace(5.999) == "6:00/km"
# --- summary_to_text --------------------------------------------------------
def test_no_none_leaks_with_missing_data():
# All-empty history: pace None, mileage None, insufficient pace trend.
text = summary_to_text(_summary(_empty_weeks()))
assert "None" not in text
def test_goal_is_included_when_given():
text = summary_to_text(_summary(_empty_weeks()), goal="run a sub-25 5K")
assert "sub-25 5K" in text
def test_goal_omitted_when_absent():
text = summary_to_text(_summary(_empty_weeks()))
assert "stated goal" not in text
def test_signals_render_as_descriptions_not_raw_keys():
text = summary_to_text(_summary(_empty_weeks(), signals=["mileage_spike"]))
assert "Weekly mileage rose more than 10%" in text
assert "mileage_spike" not in text # raw enum key must not leak through
|