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>
101 lines
4.5 KiB
Markdown
101 lines
4.5 KiB
Markdown
# 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:
|
|
|
|
```bash
|
|
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](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](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.
|