Two-cycle stale→recovery tests confirm that a non-empty fetch after timeout or empty-list correctly resets is_stale=False; no changes to main.py or aircraft.py required as recovery logic was already correct from story 3-1. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.5 KiB
Story 3.2: Automatic Recovery on Fresh Decode
Status: review
Story
As a user whose RTL-SDR has recovered, I want the display to automatically return to normal filled aircraft rendering on the next successful fetch, So that recovery requires no intervention.
Acceptance Criteria
AC1: Given the display is in stale state When HttpFetcher.fetch() returns a non-empty aircraft list Then all fetched aircraft have is_stale=False and are drawn with normal filled icons
AC2: Given the display has recovered When the next render cycle runs Then no stale outline rendering occurs for the recovered aircraft
AC3: Given a stale-then-recovery sequence When FileFixtureFetcher first returns [] (simulating stale) then returns a populated list Then the first cycle produces stale aircraft and the second produces normal fresh aircraft
Tasks / Subtasks
-
Task 1: Add recovery tests to
tests/test_stale.py(AC: #1, #2, #3)- 1.1 Add
test_recovery_after_timeout_returns_fresh - 1.2 Add
test_recovery_after_empty_returns_fresh - 1.3 Verify no code changes needed in
main.pyoraircraft.py— recovery is already correct
- 1.1 Add
-
Task 2: Run quality gates
- 2.1
python -m pytest tests/— all tests pass - 2.2
python -m ruff check .— zero violations - 2.3
python -m ruff format --check .— no formatting issues
- 2.1
Implementation Notes
Recovery logic already correct from story 3-1
The _run_one_cycle() stale detection logic in main.py is:
try:
fresh = fetcher.fetch()
except requests.Timeout:
log.warning("fetch timeout — using stale data")
fresh = []
stale_needed = True
else:
stale_needed = (len(fresh) == 0 and len(last_aircraft) > 0)
if stale_needed:
aircraft_list = [dataclasses.replace(a, is_stale=True) for a in last_aircraft]
else:
aircraft_list = fresh
When len(fresh) > 0, stale_needed is False and aircraft_list = fresh. All Aircraft instances from a fresh fetch default is_stale=False, so recovery is automatic — no code changes required.
No changes to main.py or aircraft.py
Recovery is already handled correctly. The only deliverable is two additional tests in tests/test_stale.py confirming the recovery path for both the timeout-then-fresh and empty-then-fresh scenarios.
Files changed
| File | Change |
|---|---|
tests/test_stale.py |
Add test_recovery_after_timeout_returns_fresh and test_recovery_after_empty_returns_fresh |