sam / tests /test_medication.py
notmartin's picture
Make medication start prompt friendlier
dca67b0 unverified
Raw
History Blame Contribute Delete
5.94 kB
from __future__ import annotations
import unittest
from datetime import datetime
from mr_reachy.medication import (
build_plan,
interval_dose_times,
is_confirmation_intent,
parse_medication_instruction,
)
class FakeOG:
chat_enabled = True
def __init__(self) -> None:
self.calls: list[str] = []
def complete_json(self, system_prompt: str, user_text: str, *, temperature: float = 0.0) -> str:
self.calls.append(system_prompt)
if "Extract a medication reminder schedule" in system_prompt:
return (
'{"accepted": true, "medication_name": "prednisone", '
'"frequency_per_day": 1, "duration_days": 5, "dose_times": [], '
'"advisory_note": "", "advisory_level": "routine", "reason": "ok"}'
)
return (
'{"advisory_level": "caution", '
'"advisory_note": "Small reminder: follow the label exactly and ask your pharmacist whether to take prednisone with food."}'
)
class MedicationParsingTest(unittest.TestCase):
def test_three_times_daily_without_start_time_asks_only_for_start(self) -> None:
result = parse_medication_instruction(
"Take metformin three times a day for five days.",
now=datetime(2026, 5, 28, 8, 0).astimezone(),
)
self.assertFalse(result.accepted)
self.assertEqual(result.reason, "Got it, so when are you planning to start the medication?")
def test_three_times_daily_from_start_time_schedules_eight_hourly(self) -> None:
result = parse_medication_instruction(
"Take metformin three times a day for five days starting 8am.",
now=datetime(2026, 5, 28, 8, 0).astimezone(),
)
self.assertTrue(result.accepted)
self.assertIsNotNone(result.plan)
assert result.plan is not None
self.assertEqual(result.plan.dose_times, ["08:00", "16:00", "00:00"])
self.assertEqual(len(result.plan.doses), 15)
def test_one_pill_every_morning_for_week(self) -> None:
result = parse_medication_instruction(
"Take amoxicillin every morning for a week.",
now=datetime(2026, 5, 28, 8, 0).astimezone(),
)
self.assertTrue(result.accepted)
self.assertIsNotNone(result.plan)
assert result.plan is not None
self.assertEqual(result.plan.frequency_per_day, 1)
self.assertEqual(result.plan.duration_days, 7)
self.assertEqual(result.plan.dose_times, ["09:00"])
self.assertEqual(len(result.plan.doses), 7)
def test_vague_instruction_is_rejected(self) -> None:
result = parse_medication_instruction("Take this whenever I feel bad.")
self.assertFalse(result.accepted)
self.assertIsNone(result.plan)
def test_naproxen_with_ulcer_gets_cross_check_advisory(self) -> None:
result = parse_medication_instruction(
"I have ulcer and they gave me naproxen twice a day for five days starting now.",
now=datetime(2026, 5, 28, 8, 0).astimezone(),
)
self.assertTrue(result.accepted)
self.assertIsNotNone(result.plan)
assert result.plan is not None
self.assertEqual(result.plan.medication_name.lower(), "naproxen")
self.assertEqual(result.plan.advisory_level, "cross_check")
self.assertIn("cross-check", result.plan.advisory_note)
def test_naproxen_gets_general_stomach_caution(self) -> None:
result = parse_medication_instruction(
"Take naproxen twice a day for five days starting now.",
now=datetime(2026, 5, 28, 8, 0).astimezone(),
)
self.assertTrue(result.accepted)
self.assertIsNotNone(result.plan)
assert result.plan is not None
self.assertEqual(result.plan.advisory_level, "caution")
self.assertIn("stomach", result.plan.advisory_note)
def test_at_night_maps_to_single_night_dose(self) -> None:
result = parse_medication_instruction(
"Take cetirizine at night for five days.",
now=datetime(2026, 5, 28, 8, 0).astimezone(),
)
self.assertTrue(result.accepted)
self.assertIsNotNone(result.plan)
assert result.plan is not None
self.assertEqual(result.plan.frequency_per_day, 1)
self.assertEqual(result.plan.dose_times, ["21:00"])
def test_interval_dose_times(self) -> None:
self.assertEqual(interval_dose_times("08:00", 3), ["08:00", "16:00", "00:00"])
self.assertEqual(interval_dose_times("06:00", 4), ["06:00", "12:00", "18:00", "00:00"])
def test_og_advisory_is_not_limited_to_nsaids(self) -> None:
og = FakeOG()
result = parse_medication_instruction(
"They gave me prednisone once a day for five days starting now.",
og=og,
now=datetime(2026, 5, 28, 8, 0).astimezone(),
)
self.assertTrue(result.accepted)
self.assertIsNotNone(result.plan)
assert result.plan is not None
self.assertEqual(result.plan.medication_name.lower(), "prednisone")
self.assertEqual(result.plan.advisory_level, "caution")
self.assertIn("prednisone", result.plan.advisory_note)
self.assertEqual(len(og.calls), 1)
def test_confirmation_intent(self) -> None:
self.assertTrue(is_confirmation_intent("I took it"))
self.assertTrue(is_confirmation_intent("yes I took my medicine"))
self.assertFalse(is_confirmation_intent("what time is my medicine"))
def test_build_plan_rejects_vague_name(self) -> None:
with self.assertRaises(ValueError):
build_plan(
raw_instruction="Take this 3 times a day for 5 days",
medication_name="this",
frequency_per_day=3,
duration_days=5,
)
if __name__ == "__main__":
unittest.main()