The port runs on Android and iOS and is feature-complete; the native Android app is superseded but kept, since it is still the only version that has recorded real rides. rippr-flutter-1.0-debug.apk is package com.rippr.port, deliberately different from the native com.rippr so both install side by side. Recording the same ride on both at once is the strongest available check that the port is faithful. Added INSTALL.md covering both platforms. Android is a one-line adb install; iOS has no APK equivalent and must be built and signed through Xcode with a free Apple ID, which gives a 7-day profile. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.5 KiB
T25 — the real-ride checklist
This is the only task in the plan that cannot be automated, and it is the one that matters most. 171 unit and widget tests plus 4 integration tests are green, and none of them prove the app records a ride correctly.
Adapted from the native repo's docs/TESTING.md, extended for two platforms.
Why a green suite proves nothing here
Neither simulator produces velocity. adb emu geo fix teleports the device and iOS's
simulated locations are no better, so every recorded speedKmh is 0.0. That makes the
following structurally unverifiable without riding:
- max speed, average moving speed
- moving time (everything sits under the 1.5 km/h noise floor, so it stays 00:00:00)
- speed colouring on the map — the whole path renders in one colour
- elevation gain against real, correlated GPS altitude error
- battery over a multi-hour ride
- whether iOS suspends a stationary app mid-ride
And the subtler trap, which cost v2.0 a release: when a value cannot change under test, the UI around it cannot be judged either. Max speed as the headline looked perfectly fine on an emulator where every number was zero. On a real ride it read as a frozen, broken screen.
Before you ride
Install both apps. They have different application ids on purpose
(com.rippr and com.rippr.port), so they coexist:
flutter build apk --debug && flutter install # Flutter port
adb install -r ~/dojo/samplez/rippr-2.0.1-debug.apk # native reference
Run both simultaneously on the Android ride. Recording the same ride twice gives a direct numeric comparison, which is far stronger evidence than either app alone.
The ride
Do this once on Android and once on iOS. Pocket the phone — that is the founding use case.
| # | Check | Why it is here |
|---|---|---|
| 1 | Start, pocket, ride ~20 min, stop | The actual usage pattern |
| 2 | Max speed plausible against the speedometer | Unverifiable on any simulator |
| 3 | Distance plausible against the odometer | Guards the cross-batch anchor |
| 4 | Moving time excludes stops | Noise floor behaviour on real data |
| 5 | Elevation gain near zero on flat ground | The most likely silent bug; synthetic noise is uniform, real error is correlated |
| 6 | Pause at a stop, resume — no straight line across the gap | The segment guarantee |
| 7 | Speed colouring visibly varies along the path | Cannot render in more than one colour on a simulator |
| 8 | A short ride (under 100 m) still shows streets | The v2.0 zoom bug |
| 9 | GPX opens correctly in Google Earth or Strava | Schema-valid is not the same as accepted |
| 10 | Battery drain over a multi-hour ride | Never measured, on either app |
| 11 | Pause/resume survives a screen-off stretch | Android wake lock, iOS background mode |
Android only
| # | Check |
|---|---|
| A1 | The ongoing notification appears and persists with the screen off |
| A2 | Force-stop the app mid-ride, relaunch — the ride resumes into a new segment, and the dead time is not added to distance |
| A3 | Compare totals against the native app recording the same ride |
A2 is the fix for a real bug found in the native app. See T11 in PROGRESS.md: the native version measures straight through the dead time, which a synthetic test showed adding 111 km. Confirm the port does not.
iOS only — the genuine unknown
| # | Check |
|---|---|
| I1 | The blue background-location indicator appears while recording |
| I2 | Lock the screen for 10 minutes of riding — fixes keep arriving |
| I3 | Park for 15 minutes without stopping the recording, then ride again. Does recording resume? |
| I4 | Take a phone call mid-ride; recording survives |
| I5 | Swipe the app away mid-ride — what happens? Document it, whatever it is |
I3 is the decisive test for the whole platform strategy. If iOS suspends the app when
stationary and does not reliably resume, geolocator is not sufficient and the
LocationSource seam exists precisely so flutter_background_geolocation (~$500/yr) can
be swapped in as one new implementation. Do not make that call without this data.
Recording the results
Append findings to PROGRESS.md under a T25 heading, including the numbers
from both apps where Android was recorded twice. If elevation gain on flat ground is
implausible, do not tune it blind — the native backlog says so explicitly, and the
port's parity harness (tool/parity/run.sh) means any change can be checked against the
Kotlin implementation first.