Files
openobserve/tests/mobile-testing/README.md
T
Vamsi Karthik RandShrinath Rao 6930a9b724 test(mobile): RUM SDK end-to-end suite across 4 platforms + self-contained CI (#13628)
## What this PR adds

end-to-end test suite for the **Mobile RUM SDK** under
`tests/mobile-testing/`, plus a **self-contained CI workflow** that runs
it on real emulators/simulators against an OpenObserve **built from this
PR's source**. Test / fixture / CI only — no product-code/existing test
changes

## How each test works (3 layers)

Every scenario is a real end-to-end journey, so a failure points at the
actual broken layer:

1. **Drive** — a Maestro flow taps through the app like a user
(`maestro/<track>/*.yaml`).
2. **API** — query the `_rumdata` stream and assert the telemetry is
correct (`utils/ooClient.js`, poll-and-retry for async ingestion).
3. **UI** — open the RUM dashboard and assert the sessions

## Coverage (42 tests across 4 platforms)

The **native platforms (android-native, ios-native) are now at parity
with React Native** — each new
native test (masking, network, bg/fg, user-identity, no-phone-home) was
built + validated on a real
emulator/simulator before landing.

| Capability | Layer | RN-Android | Android-native | RN-iOS | iOS-native
|
|---|---|:-:|:-:|:-:|:-:|
| Core telemetry (views/actions/handled-error/crash → `_rumdata`) | API
| ✅ | ✅ | ✅ | ✅ |
| Crash session viewable in dashboard | UI | ✅ | ✅ | ✅ | ✅ |
| Attributes: env / service / version tagging | API | ✅ | ✅ | ✅ | ✅ |
| User identity (`setUser`) | API | ✅ | ✅ | ✅ | ✅ |
| Network: fetch → resource + 4xx/5xx | API | ✅ | ✅ | ✅ | ✅ |
| Session-replay PII masking | UI | ✅ | ✅ | ✅ | ✅ |
| Background / foreground view transitions | API | ✅ | ✅ | — | ✅ |
| No-phone-home (no egress to Datadog hosts) | security | ✅ | ✅ | — | ✅
|

- Shared per-capability factories keep the specs DRY
(`utils/rumChecks.js`, `utils/coreRumSpec.js`).
- Negatives are covered: 4xx capture, PII-must-not-leak (masking), no
phone-home, handled-error ≠ crash.
- `o2-enterprise#2289` dashboard bugs are kept as inline skips that flip
green once fixed.
- Full capability × platform detail + on-device status:
`docs/COVERAGE-MATRIX.md`.

## Fixture apps + build-time config

- Four vendored apps under `apps/`: `o2-rum-tester` (React Native —
drives both RN platforms), `o2-native-android` (Kotlin), `o2-native-ios`
(Swift / xcodegen).
- Each reads its RUM target (endpoint / org / token) and SDK version
from a **build-time-overridable** config. The committed default is the
current pin, so local dev is unchanged; CI regenerates it to point at
the runner's OpenObserve and can pin the latest SDK on release.

## CI — `.github/workflows/mobile-sdk-e2e.yml` (self-contained, no
secrets)

- **Build once per OS from source.** `build_oo_linux` / `build_oo_macos`
compile OpenObserve (binary + embedded web UI) from this PR's code and
cache it. Device jobs download and run it **natively**, and the app
posts real RUM to it (Android reaches the host at `10.0.2.2`, the iOS
simulator via `localhost`). No Docker, no shared cluster, no secrets.
- **Device jobs run in parallel.** `android` (Linux + KVM emulator →
rn-android + android-native) and `ios` (macOS simulator, pinned Xcode
16.4 → rn-ios + ios-native).
- **`merge_reports`** combines both platforms into one browsable HTML
report — even when a device job fails.
- **`decide` picks which platform runs, to keep scarce macOS runners in
check:**
- PR touching Android or shared mobile-RUM code → **Android auto-runs**;
iOS is gated behind the `mobile-e2e` label.
  - `mobile-e2e` label → both platforms (full pre-merge gate).
- `repository_dispatch(mobile-sdk-release)` from an SDK repo → runs that
SDK's platform (companion PRs wire this up:
openobserve-react-native-rum#3, openobserve-sdk-android#1,
openobserve-sdk-ios#1).
  - `workflow_dispatch` → manual, choose platforms.

*Separate workflow :* it needs macOS **and** Android emulators, builds 4
phone apps, and is dispatch-driven — matching the repo's existing
per-suite split

## Status

Green end-to-end on GitHub runners (Android + iOS device jobs + merge) :
https://github.com/openobserve/openobserve/actions/runs/31733717758/job/94565520891

---------

Co-authored-by: Shrinath Rao <shnath@openobserve.ai>
2026-08-20 08:13:35 +00:00

118 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Mobile RUM SDK — End-to-End Test Suite
E2E tests for OpenObserve's **Mobile RUM SDK** (`@openobserve/mobile-react-native` and native
tracks). Each test drives a real mobile app on an emulator/simulator, then asserts the telemetry
both **at the data layer** (OpenObserve Search API) and **at the product layer** (the RUM
dashboard UI) — because most mobile-RUM defects live in the dashboard, not the pipeline.
## The 3-layer pattern
Every scenario is the same shape, threaded by `session_id`:
```
1. DRIVE Maestro flow taps through the app (maestro/<track>/*.yaml)
2. API query _rumdata → assert data is correct (utils/ooClient.js)
3. UI open the dashboard → assert it renders (pages/rumDashboardPage.js)
```
Why both layers? Nearly every bug found in manual testing (Error Tracking, Web Vitals,
breadcrumbs, Traces) was a **display bug**: the data was correct in `_rumdata` but the dashboard
failed to show it. An API-only suite would have been green on a broken product.
## Layout
```
mobile-testing/
├── apps/ Vendored fixture apps (o2-rum-tester, o2-native-android, o2-native-ios)
├── maestro/ Maestro flows per track (react-native, android-native, ios-native, ios-react-native)
├── specs/ Playwright specs (rn-android.*, rn-ios.*, android-native.*, ios-native.*)
├── pages/rumDashboardPage.js Dashboard page object (login, open session, masking guard)
├── utils/
│ ├── ooClient.js OpenObserve Search API client (poll-and-retry)
│ ├── rumChecks.js per-capability test factories (attributes/user/network/masking/…)
│ ├── coreRumSpec.js the crash → dashboard core journey
│ ├── maestro.js Maestro flow runner
│ ├── adb.js device-level Android steps
│ └── config.js env loader
├── docs/ Coverage matrix, CI notes, test-case matrix
├── playwright.config.js
└── .env / .env.example instance URL, org, creds, app id
```
## Prerequisites
- **Node 20+**, **JDK 17**, Android SDK + an emulator (AVD)
- **Maestro** CLI: `curl -Ls "https://get.maestro.mobile.dev" | bash`
- The app under test (`com.o2rumtester`) — its source lives **in this suite** at
`apps/o2-rum-tester/`. Build + install it:
```bash
cd apps/o2-rum-tester && npm install # postinstall auto-applies the SDK build fix
(cd android && ./gradlew assembleRelease)
adb install -r android/app/build/outputs/apk/release/app-release.apk
```
- A reachable OpenObserve instance with a RUM token wired into the app (see `.env` and
`apps/o2-rum-tester/App.tsx`)
## Setup
```bash
cp .env.example .env # fill in OO_URL / OO_ORG / OO_USER / OO_PASS (quote passwords with #)
npm install
npx playwright install chromium
```
## Run
```bash
# one platform (Playwright projects)
npx playwright test --project=rn-android
npx playwright test --project=android-native
npx playwright test --project=rn-ios # needs a booted iOS simulator
npx playwright test --project=ios-native # needs a booted iOS simulator
# by tag
npx playwright test --grep @crash
npx playwright test --grep @masking
npx playwright test --grep @known-bug # the skipped #2289 markers
```
### Coverage (all four mobile tracks) — 42 tests
Each platform has a **core RUM** bundle (`utils/coreRumSpec.js`: views + actions + handled error +
native crash in `_rumdata`, then the crashed session rendering in the dashboard) **plus**
per-capability specs built from shared factories in **`utils/rumChecks.js`** — so the platforms stay
at parity without copy-paste:
- `attributesSuite` — env / service / version tagging
- `userIdentitySuite` — events attributed to the set user (usr_* fields)
- `networkSuite` — a successful fetch is a resource (**positive**) + a 4xx status is captured (**negative**)
- `maskingSuite` — no PII leaks into the session replay (MASK_ALL)
- `bgFgSuite` — a pre-background view and a post-foreground view share one session
- `noPhoneHomeAndroidSuite` — the installed APK contains zero Datadog hosts (**security/negative**)
| Project | App | Service | Specs |
|---|---|---|---|
| `rn-android` | `apps/o2-rum-tester` (Android) | `o2-rum-tester` | crash, network(+404), handled-error, views, masking, attributes, user-identity, background-foreground, no-phone-home |
| `android-native` | `apps/o2-native-android` | `o2-native-android` | core bundle, attributes, user-identity, no-phone-home |
| `rn-ios` | `apps/o2-rum-tester` (iOS) | `o2-rum-tester` | core bundle, network(+404), attributes, user-identity, masking |
| `ios-native` | `apps/o2-native-ios` | `o2-native-ios` | core bundle, attributes |
See **`docs/COVERAGE-MATRIX.md`** for the full capability×platform matrix, on-device validation
status, and the deferred follow-ups (native/iOS background-foreground, native network/masking,
iOS-native user identity — each needs a fixture-app change or a background harness).
Prereqs: Android emulator booted for the Android projects; an iOS simulator booted (udid in
`.env` `IOS_SIM_UDID`) for the iOS projects; the fixture apps built + installed (see `apps/`).
Tags: `@mobile @rn-android @rn-ios @android-native @ios-native @P0 @P1 @crash @network @negative @errors @views @replay @masking @lifecycle @attributes @user-identity @security @known-bug`.
## Notes
- **The known Error-Tracking outage (o2-enterprise#2289) is a `test.fixme` skip** inline in the
relevant spec — no separate file or project. It stays skipped and turns into a real assertion
when the bug is fixed.
- **Ingestion is async** — assertions poll-and-retry; never assert instantly.
- **Session isolation** — the current specs scope by `service` + time window. For parallel/CI runs,
stamp a unique run-id as a RUM global attribute in the app and filter on it (see `docs/CI-NOTES.md`).
- **Fixture apps** — the four apps live in `apps/` (each builds against the SDK from npm/Maven/SPM);
iOS tracks additionally need Xcode/simulator. Build/run steps are in each app + `docs/CI-NOTES.md`.