Isolate daily summary race test stubs on Windows#7792
Conversation
83be990 to
008f6f6
Compare
Greptile SummaryThis PR isolates
Confidence Score: 4/5Safe to merge; changes are test-only and the core isolation mechanic works correctly for the stated goal. The stub teardown approach is sound and the 15-test run in both orderings validates the primary goal. Two residual gaps: the _NY_TZ timezone is fixed at UTC-5 regardless of DST, which could produce an off-by-one date for lock keys when tests run during EDT hours near midnight; and utils.other.notifications itself is not removed from sys.modules after cleanup. backend/tests/unit/test_daily_summary_race_condition.py — specifically the _NY_TZ fixed offset and the fact that utils.other.notifications lingers in sys.modules after stub cleanup. Important Files Changed
Reviews (1): Last reviewed commit: "test(backend): isolate daily summary rac..." | Re-trigger Greptile |
| def tzname(self, dt): | ||
| return self._zone.tzname(dt) |
There was a problem hiding this comment.
Fixed EST offset ignores Daylight Saving Time
_NY_TZ is hardcoded to UTC-5 (EST), but America/New_York observes EDT (UTC-4) from roughly mid-March through early November. Any test that runs during DST and calls _send_summary_notification with the America/New_York timezone will compute a local date that is one hour behind the real local time. Near midnight, this produces a lock key for the previous day instead of the current day, which could mask failures or produce spurious passes in the date-boundary logic.
There was a problem hiding this comment.
Addressed in the current head: _PytzEasternTimezone now switches between EST and EDT using the US DST transition bounds, so the New York fallback is not fixed at UTC-5.
| sub_mod = _stub_module("utils.subscription") | ||
| sub_mod.is_trial_paywalled = MagicMock(return_value=False) |
There was a problem hiding this comment.
utils.other.notifications stays in sys.modules after cleanup
The cleanup loop removes every name in _STUB_MODULE_NAMES, but utils.other.notifications was imported with a real import statement and is not tracked in that set. It therefore remains in sys.modules for the rest of the process, carrying live references to all the stub MagicMock objects as its module-level globals. Any later test file that does import utils.other.notifications will receive this already-initialised instance with stubs baked into conversations_db, daily_summaries_db, etc., rather than a clean import. This is the same class of problem the PR is solving for database.daily_summaries.
There was a problem hiding this comment.
Addressed in the current head: the test keeps a handle to the imported module for patch.object(...), then explicitly removes utils.other.notifications from sys.modules after saving the collaborator references.
008f6f6 to
7b2ea57
Compare
Summary
pytztest stub sotest_daily_summary_race_condition.pycan collect in a minimal Windows backend venv.utils.*package entries left by earlier tests before importing the realutils.other.notificationsmodule.utils.other.notifications, then remove the stub modules and the importedutils.other.notificationsmodule fromsys.modulesafter import.sys.modules.Why
On a minimal Windows backend environment, this test failed at collection because
pytzwas not installed. After stubbingpytz, the file also pollutedsys.moduleswithdatabase.daily_summaries, which made the adjacenttest_daily_summary_regenerate.pyimport a stale stub instead of the real module during collection.In the broader Windows collect-only smoke path, earlier tests can also leave orphaned
utils.*modules without a parentutilspackage, which raisesKeyError: 'utils'while importingutils.other.notifications. This keeps the race-condition test self-contained while allowing later daily-summary tests and the broader collection pass to proceed cleanly.Testing
python -m pytest tests\unit\test_daily_summary_race_condition.py -q-> 13 passedpython -m pytest tests\unit\test_daily_summary_race_condition.py tests\unit\test_daily_summary_regenerate.py -q-> 15 passedpython -m pytest tests\unit\test_daily_summary_regenerate.py tests\unit\test_daily_summary_race_condition.py -q-> 15 passedpython -m black --line-length 120 --skip-string-normalization tests\unit\test_daily_summary_race_condition.py --checkpython -m py_compile tests\unit\test_daily_summary_race_condition.pygit diff --check -- backend/tests/unit/test_daily_summary_race_condition.py