Skip to content

ci: run the Android instrumented tests on an emulator - #137

Merged
aaronbrethorst merged 4 commits into
OneBusAway:mainfrom
diveshpatil9104:ci/android-instrumented-tests
Oct 6, 2026
Merged

aaronbrethorst merged 4 commits into
OneBusAway:mainfrom
diveshpatil9104:ci/android-instrumented-tests

Conversation

@diveshpatil9104

@diveshpatil9104 diveshpatil9104 commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #132

The Android workflow never ran src/androidTest, and never even compiled it, since assembleDebug builds the app APK and not the test APK. ScreenFlowTest and KeystoreCryptorTest could break and CI stayed green.

This PR adds an instrumented job beside the android job, so unit test feedback stays fast and an emulator problem fails a job of its own. It runs connectedDebugAndroidTest with reactivecircus/android-emulator-runner@v2 on an API 36 x86_64 default image (36 is our targetSdk, and the image has the Android Keystore), with KVM enabled per the action's README and the AVD cached by API level.

The three #115 review fixes ship here because this job is what tests them:

  • Resume buttons stay disabled until the stored trip loads, since End Shift did nothing before then
  • Resume screen now scrolls at large font sizes, with a Box doing the centering that Arrangement.Center cannot do under verticalScroll
  • MainActivity now calls startTracking whenever active turns true while resumed, instead of checking once in onResume. This covers a START_STICKY restart that turns active after the activity resumed and then degrades. That is harmless on a healthy service (which only requests updates when none are running), and going inactive never triggers it, so an ended trip is not restarted. I could not reproduce the race on demand, so this covers the window rather than a repro.

Verification

  • Locally: assembleDebug, testDebugUnitTest, assembleRelease, and assembleDebugAndroidTest pass
  • All 17 instrumented tests pass on an API 32 emulator
  • Reverting each fix fails its new test (for the re-arm: dropping distinctUntilChanged, dropping the filter, or the old one-shot check)
  • One local run in four hit "No compose hierarchies found" in an unchanged tracking screen test; it did not recur in three more runs

Summary by CodeRabbit

  • Bug Fixes
    • Resume and end-shift actions are now unavailable until a trip has loaded, preventing actions when trip details aren’t ready.
    • The resume screen can scroll when content doesn’t fit, including at larger text sizes.
    • Active trip tracking now restarts when the app returns to the foreground and tracking is still active, including after tracking becomes active while the app is open.

@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: fd043446-4d5d-4f7b-85c8-9bf5ba94387d
📥 Commits

Reviewing files that changed from the base of the PR and between b9f2790 and cccd07a.

📒 Files selected for processing (11)
  • .github/workflows/android.yml
  • android/app/src/androidTest/kotlin/org/onebusaway/vehicletracker/data/KeystoreCryptorTest.kt
  • android/app/src/androidTest/kotlin/org/onebusaway/vehicletracker/ui/ScreenFlowTest.kt
  • android/app/src/main/kotlin/org/onebusaway/vehicletracker/MainActivity.kt
  • android/app/src/main/kotlin/org/onebusaway/vehicletracker/data/Cryptor.kt
  • android/app/src/main/kotlin/org/onebusaway/vehicletracker/service/LocationTrackingService.kt
  • android/app/src/main/kotlin/org/onebusaway/vehicletracker/service/RearmWhenActive.kt
  • android/app/src/main/kotlin/org/onebusaway/vehicletracker/ui/resume/ResumeShiftScreen.kt
  • android/app/src/test/kotlin/org/onebusaway/vehicletracker/data/SessionStoreTest.kt
  • android/app/src/test/kotlin/org/onebusaway/vehicletracker/data/VehiclePrefsStoreTest.kt
  • android/app/src/test/kotlin/org/onebusaway/vehicletracker/service/RearmWhenActiveTest.kt

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The Android workflow now runs instrumented tests in an emulator. The resume screen supports scrolling and disables actions until a trip is loaded. MainActivity re-arms tracking while resumed when tracking state is active.

Changes

Instrumented Android CI

Layer / File(s) Summary
Run instrumented tests in an emulator
.github/workflows/android.yml, android/app/src/androidTest/kotlin/org/onebusaway/vehicletracker/data/KeystoreCryptorTest.kt, android/app/src/main/kotlin/org/onebusaway/vehicletracker/data/Cryptor.kt, android/app/src/test/kotlin/org/onebusaway/vehicletracker/data/SessionStoreTest.kt, android/app/src/test/kotlin/org/onebusaway/vehicletracker/data/VehiclePrefsStoreTest.kt
The workflow configures an Android 36 x86_64 emulator and runs connected debug instrumented tests. Test comments describe the CI job and JVM test boundaries.

Tracking re-arm behavior

Layer / File(s) Summary
Re-arm tracking from active state
android/app/src/main/kotlin/org/onebusaway/vehicletracker/service/RearmWhenActive.kt, android/app/src/main/kotlin/org/onebusaway/vehicletracker/MainActivity.kt, android/app/src/main/kotlin/org/onebusaway/vehicletracker/service/LocationTrackingService.kt, android/app/src/test/kotlin/org/onebusaway/vehicletracker/service/RearmWhenActiveTest.kt
MainActivity collects tracking state while resumed. The collector calls startTracking for active states. Tests cover initial and subsequent active states, inactive states, and changes to problem and fix fields.

Resume Shift screen

Layer / File(s) Summary
Adjust resume screen layout and actions
android/app/src/main/kotlin/org/onebusaway/vehicletracker/ui/resume/ResumeShiftScreen.kt, android/app/src/androidTest/kotlin/org/onebusaway/vehicletracker/ui/ScreenFlowTest.kt
The screen scrolls when content exceeds available height. Resume and End Shift actions are disabled when no trip is loaded or an ending operation is underway. Instrumented tests check action availability and scrolling at large font scale.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Other

Sequence Diagram(s)

sequenceDiagram
  participant MainActivity
  participant rearmWhenActive
  participant TrackingState
  participant ServiceController
  MainActivity->>rearmWhenActive: collect tracking state while RESUMED
  rearmWhenActive->>TrackingState: observe active values
  TrackingState-->>rearmWhenActive: emit active state
  rearmWhenActive->>ServiceController: startTracking()
Loading

Merge Risk: ⚪ Minimal · up to cccd0

No merge-blocking issue is established. Confirm the new emulator job passes as part of normal CI checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to cccd0

Tracking recovery retains the existing trip ownership and permission controls, and no introduced security bypass was identified. Remaining uncertainty concerns concurrent lifecycle transitions and the new CI runner dependencies and permissions.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The application-side sensitive outcome is location reporting for the device's active trip through the existing reporting path. The CI-side change adds PR-code execution and KVM access on a hosted runner; repository token authority cannot be determined from the workflow alone.

Trust Boundaries and Controls

  • observed — Launching the activity does not itself create an active trip. Recovery still targets a non-exported service, loads existing trip ownership, requests location through platform enforcement, and handles SecurityException by entering degraded mode. Reporting retains the existing Bearer-token authentication path.

Resilience and Maintainability Implications

  • observed — On ordinary successful or local end-shift execution, durable trip ownership is cleared before the stop request, and service stop or destruction resets runtime tracking state. An API end failure preserves ownership for retry. These unchanged sequential transitions provide counterevidence to automatic restart after an inactive emission, but do not establish atomic cleanup under cancellation or concurrency.

Hardening Proposals

  • proposed — Declare a least-privilege workflow token policy, such as contents: read, and pin the newly added emulator and cache actions to reviewed commit revisions. This would bound dependency authority without relying on repository defaults or mutable version tags.
🚥 Pre-merge checks | ✅ 3 | ❌ 1 | ❓ 1

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 10 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive [ #132 ] The workflow triggers on pull requests that change android/** and adds an instrumented job that runs :app:connectedDebugAndroidTest on API 36. This covers ScreenFlowTest and `Keystore… Provide evidence that the new API 36 instrumented CI job passes, including ScreenFlowTest and KeystoreCryptorTest.
✅ Passed checks (3 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed [ #132 ] All changes support the instrumented-test CI job or the three accompanying Resume Shift and tracking fixes. The added and updated tests and test comments directly support those objectives. No…
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: running Android instrumented tests on an emulator in CI.
Full details: Linked Issues check

Explanation

[ #132 ] The workflow triggers on pull requests that change android/** and adds an instrumented job that runs :app:connectedDebugAndroidTest on API 36. This covers ScreenFlowTest and KeystoreCryptorTest. The PR also implements the three accompanying fixes: Resume Shift actions wait for the trip to load, the screen scrolls, and tracking re-arms when state becomes active while resumed; the summary reports supporting tests. However, the available evidence does not establish that the new API 36 CI job passed. The reported local emulator run used API 32.

Full details: Docstring Coverage

Explanation

Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 10 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@aaronbrethorst

Copy link
Copy Markdown
Member

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

@aaronbrethorst aaronbrethorst left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Divesh. I read the job log, not just the green check: the emulator booted from the snapshot and ran all 17 instrumented tests. The bundled #115 fixes (resume buttons, scrolling, re-arm while resumed) all behave the same as before, and rearmWhenActive has unit tests. Merging.

Follow-ups: adding the emulator/system-image version to the AVD cache key would avoid stale snapshots. instrumented should also become a required check.

@aaronbrethorst
aaronbrethorst merged commit c25e9f5 into OneBusAway:main Oct 6, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Run Android instrumented tests in CI

2 participants