Files
samplez/rippr-flutter-src/docs/port/REAL-RIDE-CHECKLIST.md
Dylan 0bc42b2e5a Add the Rippr Flutter port: source, history bundle, and installable APK
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>
2026-08-15 22:37:45 -05:00

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.