Repository navigation
test: cover WHOOP 5 gap regressions on both platforms - #2056
Conversation
ryanbr
left a comment
There was a problem hiding this comment.
Reviewed at f4fcbb8. This is the layer my own tests for the explanation did not reach, and it is the
right one to add. Approving.
What it covers that the existing tests do not. The predicate and the two store reads were each
pinned in isolation. This drives the whole path: analyzeRecent into the persisted row, the row plus
the production queries into the predicate, and then the same night again. That is where a regression
would actually live, and the lifecycle it walks is the one the wearer walks. Beats absent, so no claim.
Legacy beats present, so the claim stands. A re-offload arriving labelled, so the promotion lands, the
night scores, and the claim goes. Then a re-score on top, which is the case I would have missed: a
cache hit must not revive an explanation for a night that now has a Charge.
Both false-positive directions are pinned, which for a diagnostic matters more than the positive
one. A night with no beats at all is not blamed on the units, and a night with valid HRV but no
Charge stays ordinary calibration rather than being handed a cause it does not have. The WHOOP 4 case
asserts the whole mechanism stays off a family it was never about. Those three are what stop the
explanation growing into a catch-all for an empty ring.
insert(...).rr == 0 on the labelled re-offload is a good detail. It pins that a re-offload
changes provenance rather than adding a second copy of the night, which is the part of the promotion
path that would be invisible in a test that only checked the score came back.
Verified rather than taken on trust: I merged this onto current main, which is two commits ahead of
its base, and ran the Android class. Eighteen tests, no failures, and both new cases present in the
XML rather than filtered to nothing. All five checks are green on the PR's own head.
Two notes, neither blocking:
showsLegacyGaprebuilds the view's assembly rather than calling it, so what is pinned is the
predicate and the queries, not the wiring. The owner it passes is given to it; the shipped code
resolves that itself, and given how much re-pair alias history this area carries, the owner
resolution is the part I would least like to be uncovered. Both platforms would stay green if a
view started asking about the wrong strap. Extracting the assembly into one function the view and
the test both call would close it, the way the hosted trend cards ended up sharing their resolver
rather than each having one.- The Swift
seedBaselinewalks back by subtracting 86,400 seconds and reformatting, where the Kotlin
twin usesLocalDate.minusDays. Across a DST boundary the arithmetic version can repeat or skip a
calendar date, which here costs one of eight seeded days and so cannot fail the test. Worth knowing
it is the same shape that did bite a day-key helper recently, and the calendar call is no longer.
Thanks @Trillient. Tests that walk the lifecycle rather than the unit are the harder ones to write and
the ones that survive a refactor.
What this PR does
Add regression coverage for the WHOOP 5 missing-score explanation introduced in
dfb69e67. The Swift and Kotlin tests run nightly scoring against stored data, then feed the persisted daily row and the real first-recorded/first-scorable queries into the sameWhoop5RR.legacyUnscorableNightpredicate used by Today.The final diff changes two test files. Production code, UI copy, and the historical date bounds match
main.Type of change
How it was tested
The new lifecycle coverage pins three cases:
Existing re-pairing/alias, transport-window and restaging regressions remain intact. These are scorer/store/predicate tests; they do not render the UI.
IntelligenceRRSourceTestspassed locally. The Apple CI run also passed its full macOS test run and iOS simulator build.RecoveryDriversTeston JetBrains JDK 21.0.8 (-0.5versus-0.4999999999999929).Checklist
docs/CONTRIBUTING.mdRelated issues
Follow-up to #2046 and the gap explanation in
dfb69e67. Related to #1505.