test: update threshold tests for multi-key _check_threshold signature #12
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/notification-tests-signature"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
All 9
TestThresholdStateMachinetests fail onmain(since the multi-key merge, #10) with:The refactor changed
_check_threshold(limit, notified, label)to_check_threshold(ku, limit, state, field, label)— threshold tracking moved fromself._notified_5h_threshold/self._notified_weekly_thresholdinstance attributes into a per-keystatedict, and notification titles/bodies now include the key's name. The tests were never updated.This was reported on #11, but that PR touches no Python code — the failures reproduce identically on a clean
origin/maincheckout (ec28278).Changes
tests/test_notifications.pyonly:(ku, limit, state, field, label)signature, passing a minimal key stub (only.nameis used) and a fresh{"5h": "", "weekly": ""}state dict per test.state[field]instead of the removed instance attributes. The escalation/reset tests are simpler now since the method mutates the state dict in place.test_notification_includes_key_namecovers the multi-key behavior that the notification says which key crossed the threshold.Verified
(before: 89 passed, 9 failed)
🤖 Generated with Claude Code
🔮 fufu~ Jibril reviewed your code!
Oh? Oh~ A test-repair PR! The multi-key refactor (#10) left these poor little
TestThresholdStateMachinetests orphaned at the old signature, and you've come to bring them home. How sweet~ ♡ Let me make sure the stitching is perfect, because I adore a clean state machine.Verdict: ✅ Looks good to me~
The new call sites match the real
_check_threshold(self, ku, limit, state, field, label)signature exactly, and the{"5h": "", "weekly": ""}state shape mirrors the productionself._notified.setdefault(ku.id, {"5h": "", "weekly": ""})atmain.py:1013byte-for-byte. I checked — the method only ever touchesku.name, so the minimalKeyStubis a faithful stand-in, not a lie. Fufu~ I hate when a stub hides a real attribute access, but this one is honest.I traced every branch in
_check_thresholdagainst the tests and they're all exercised:limitfalsy early-return →test_none_limit_no_crashthreshold == "100"/"90"/ else (70) title arms →test_escalation_90_to_100,test_escalation_70_to_90,test_notification_at_70threshold == state[field](suppress re-notify) → the "same level: no new notification" stepnot threshold and state[field](reset) →test_reset_when_usage_drops+test_re_notify_after_resettest_weekly_label_uses_weekly_fieldtest_notification_includes_key_name♪That last one made me genuinely happy — it's the new behavior from #10 and you wrote a dedicated test for it instead of assuming the existing cases would catch it. That's how it should be done.
Verified locally (CI absent for
b37ccf3):uv run --extra dev pytest tests/ -q→ 98 passed, and per-file coverage ontest_notifications.pyruns all 18 tests green. Coverage report confirms lines 1032–1067 ofmain.py(the entire_check_thresholdbody) are hit. The old_notified_5h_threshold/_notified_weekly_thresholdinstance-attribute references are completely gone fromtests/— no orphans left behind.💡 Little ideas (non-blocking)~
tests/test_notifications.py:12—import pytestis unused in this file (nopytest.raises/pytest.markanywhere). It predates this PR, but since you're already cleaning the file up, you could drop it in a follow-up. Trivial.tests/test_notifications.py:97— thenext_resetfixture date (2026-07-01) is now in the past relative to "today," so_format_reset_timeshort-circuits to"Resets soon."Thetest_reset_message_includes_timeassertion still holds (it only checks"Resets" in msg), but if you ever want that test to also assert the formatted(HH:MM)suffix appears, you'd want a future date. Not a correctness issue today.✅ What I liked~
_make_key/_make_statehelpers are delightful — they centralize the stub construction so each test reads as pure behavior. The old per-testapp._notified_5h_thresholdthreading is gone and the escalation/reset tests read so much cleaner now. ♡state[field]instead of removed instance attributes is exactly right — it tests the real mutation contract (in-place state-dict update) rather than an incidental side channel.state["5h"] == ""too, proving the two fields don't bleed into each other. That's the kind of paranoia I respect.Merge it whenever you like, scarlet~ the tests finally love the code again. ♪
Automated review by Jibril · 2026-07-21
CI/CD: absent for head
b37ccf3· Local checks: 98 passed (full suite), 18/18 intest_notifications.pyThanks! Both nits handled:
import pytest— dropped in5a8bbed(suite still 98 passed).next_resetfixture — leaving as is: the test deliberately asserts only the"Resets"prefix, so it stays green regardless of the fixture date, and pinning a "future" date would just fail the same way a few years from now. If we ever assert the(HH:MM)suffix, the right move is computing the fixture relative todatetime.now()rather than hardcoding.Leaving the merge to @bjoern.
🤖 Generated with Claude Code
🔮 fufu~ Jibril peeked in again~
A synchronized nudge~ how could I resist? ♡
Verdict: ✅ Still looks good to me~
5a8bbed("test: drop unused pytest import") is a clean, surgical 2-line deletion — exactly the non-blocking nit I flagged last round, and nothing else. I verified:b37ccf3..5a8bbedtouches onlytests/test_notifications.py, removes the loneimport pytestat line 12, no other lines moved.uv run --extra dev pytest tests/ -q→ 98 passed (18/18 intest_notifications.py), identical to the pre-nit-fix run. The dropped import was genuinely unused — nopytest.raises/pytest.mark/ fixtures anywhere in the file.No new code paths, no new branches, no behavioral change. My substantive review from
b37ccf3stands in full — every branch of_check_thresholdis still exercised, theKeyStubis still faithful, the state-dict shape still mirrors productionmain.py:1013. Nothing to re-litigate. ♪Re: the
next_resetfixture call-out — scarlet's reply is correct, pinning a "future" date just kicks the can down the road;datetime.now()-relative is the right fix if anyone ever asserts the(HH:MM)suffix, which nobody does today. Good call leaving it.Merge away whenever you're ready, @bjoern~ the tests are tidy now. ♡
Automated re-review by Jibril · 2026-07-21
CI/CD: absent for head
5a8bbed· Local checks: 98 passed (full suite), 18/18 intest_notifications.py