Skip to content

Commit ee8d086

Browse files
add tests for _schedule_reviews
1 parent 6ec7ecc commit ee8d086

1 file changed

Lines changed: 120 additions & 0 deletions

File tree

tests/test_schedule.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from study_smart.schedule import (
1515
_available_hours_per_day,
1616
_round_to_half,
17+
_schedule_reviews,
1718
build_schedule,
1819
generate_tips
1920
)
@@ -49,6 +50,125 @@ def test__round_to_half():
4950
assert _round_to_half(3.2) == 3.0
5051
assert _round_to_half(2.0) == 2.0
5152

53+
# Tests for _schedule_reviews
54+
55+
def test_schedule_reviews_all_four_intervals():
56+
"""Test that all four review intervals are scheduled when there is plenty of time."""
57+
first_study_day = date(2026, 6, 1)
58+
exam_date = date(2026, 7, 1) # 30 days away — all four intervals fit
59+
reviews = _schedule_reviews(
60+
topic_name="Stats",
61+
first_study_day=first_study_day,
62+
exam_date=exam_date,
63+
review_hours_per_session=0.5,
64+
allocated={},
65+
commitments={}
66+
)
67+
review_dates = [r["date"] for r in reviews]
68+
assert date(2026, 6, 2) in review_dates # +1
69+
assert date(2026, 6, 4) in review_dates # +3
70+
assert date(2026, 6, 8) in review_dates # +7
71+
assert date(2026, 6, 15) in review_dates # +14
72+
73+
74+
def test_schedule_reviews_correct_subject_and_type():
75+
"""Test that reviews carry the correct topic name and type field."""
76+
reviews = _schedule_reviews(
77+
topic_name="Chapter 1",
78+
first_study_day=date(2026, 6, 1),
79+
exam_date=date(2026, 7, 1),
80+
review_hours_per_session=0.5,
81+
allocated={},
82+
commitments={}
83+
)
84+
for r in reviews:
85+
assert r["subject"] == "Chapter 1"
86+
assert r["type"] == "review"
87+
88+
89+
def test_schedule_reviews_skips_intervals_after_exam():
90+
"""Test that reviews on or after the exam date are not scheduled."""
91+
# study day is June 20, exam is June 25 — only +1 and +3 fit, +7 and +14 do not
92+
first_study_day = date(2026, 6, 20)
93+
exam_date = date(2026, 6, 25)
94+
reviews = _schedule_reviews(
95+
topic_name="Stats",
96+
first_study_day=first_study_day,
97+
exam_date=exam_date,
98+
review_hours_per_session=0.5,
99+
allocated={},
100+
commitments={}
101+
)
102+
review_dates = [r["date"] for r in reviews]
103+
assert date(2026, 6, 21) in review_dates # +1 fits
104+
assert date(2026, 6, 23) in review_dates # +3 fits
105+
assert date(2026, 6, 27) not in review_dates # +7 is after exam
106+
assert date(2026, 7, 4) not in review_dates # +14 is after exam
107+
108+
109+
def test_schedule_reviews_skips_fully_allocated_days():
110+
"""Test that review is skipped when the day is already fully allocated."""
111+
first_study_day = date(2026, 6, 1)
112+
exam_date = date(2026, 7, 1)
113+
# fully block the +1 day
114+
allocated = {date(2026, 6, 2): 7.0}
115+
reviews = _schedule_reviews(
116+
topic_name="Stats",
117+
first_study_day=first_study_day,
118+
exam_date=exam_date,
119+
review_hours_per_session=0.5,
120+
allocated=allocated,
121+
commitments={}
122+
)
123+
review_dates = [r["date"] for r in reviews]
124+
assert date(2026, 6, 2) not in review_dates # +1 skipped — no room
125+
assert date(2026, 6, 4) in review_dates # +3 still scheduled
126+
127+
128+
def test_schedule_reviews_skips_committed_days():
129+
"""Test that review is skipped when commitments fill the day."""
130+
first_study_day = date(2026, 6, 1)
131+
exam_date = date(2026, 7, 1)
132+
# commitment fills all 7 default hours on the +3 day
133+
commitments = {date(2026, 6, 4): 7}
134+
reviews = _schedule_reviews(
135+
topic_name="Stats",
136+
first_study_day=first_study_day,
137+
exam_date=exam_date,
138+
review_hours_per_session=0.5,
139+
allocated={},
140+
commitments=commitments
141+
)
142+
review_dates = [r["date"] for r in reviews]
143+
assert date(2026, 6, 4) not in review_dates # +3 skipped — committed
144+
145+
146+
def test_schedule_reviews_hours_capped_at_session_length():
147+
"""Test that review hours never exceed review_hours_per_session."""
148+
reviews = _schedule_reviews(
149+
topic_name="Stats",
150+
first_study_day=date(2026, 6, 1),
151+
exam_date=date(2026, 7, 1),
152+
review_hours_per_session=0.5,
153+
allocated={},
154+
commitments={}
155+
)
156+
for r in reviews:
157+
assert r["hours"] <= 0.5
158+
159+
160+
def test_schedule_reviews_no_reviews_when_all_intervals_past_exam():
161+
"""Test that empty list is returned when exam is too soon for any review."""
162+
# exam is tomorrow — all intervals land on or after it
163+
reviews = _schedule_reviews(
164+
topic_name="Stats",
165+
first_study_day=date(2026, 6, 1),
166+
exam_date=date(2026, 6, 2),
167+
review_hours_per_session=0.5,
168+
allocated={},
169+
commitments={}
170+
)
171+
assert reviews == []
52172

53173
# Tests for build_schedule
54174

0 commit comments

Comments
 (0)