Overview / goals
Design a test pyramid that gives fast feedback (unit), realistic behaviour (integration with simulated backend), and full-user validation (E2E on devices), while making tests deterministic and CI-reliable under flaky networks.
Unit tests (fast, deterministic)
- Tools: iOS XCTest + URLProtocol-based stubs or OHHTTPStubs; Android JUnit + Mockito + OkHttp MockWebServer.
- Strategy: isolate networking layer by injecting an HTTP client interface; mock network responses and clocks; assert request formation, retries, and error handling.
- Example: use MockWebServer to enqueue JSON and verify headers and retry counts.
Integration tests (simulated backend)
- Tools: WireMock standalone / Docker, MockWebServer for Android, local Swift/Vapor server for iOS.
- Strategy: run app build pointing to WireMock host in a test profile; test real serialization, persistence, and retry/backoff logic against scripted latency, 500s, auth flows.
- Use contract tests (Pact) to verify API expectations between mobile and backend teams.
Deterministic replay of server responses
- Tools: WireMock recordings, VCR-like recordings, or saved MockWebServer enqueues; Charles/mitmproxy session dumps for complex flows.
- Strategy: record golden interactions, store mappings in repo, run replay mode in CI to reproduce specific bugs. Pin timestamps/UUIDs via dependency injection to avoid nondeterminism.
End-to-end on device farms with flaky networks
- Tools: Firebase Test Lab, AWS Device Farm, BrowserStack App Automate; Espresso/XCUITest for automation.
- Network conditions: use Network Link Conditioner (iOS), tc/netem on device farm VMs, or device-farm network shaping to simulate latency, jitter, loss, and throttling.
- Strategy: run E2E suites under multiple profiles (good/3G/edge/packet-loss). Capture logs, videos, and HARs. Validate UX: offline flows, sync, resume-after-reconnect.
Flaky-test mitigation & observability
- Mark long-running flaky scenarios as nightly; for PRs run fast smoke E2E.
- Auto-rerun transient failures (1–2 retries) with strict logging; quarantine persistent flaky tests.
- Collect telemetry: screenshots, network traces, device logs, and deterministic seeds.
CI strategy
- Pipeline tiers:
- Pre-merge: unit tests + static analysis (Xcode Analyzer, detekt/ktlint), run in parallel on GitHub Actions / CircleCI / Bitrise.
- Merge gate: integration tests against WireMock in Docker, run in CI matrix (iOS/Android, API versions).
- Post-merge/nightly: E2E on device farms (Firebase/AWS/BrowserStack), network-shaping matrix, contract verification.
- Artifacts: store recordings, device logs, videos for debugging. Use caching for builds, and split tests to parallel device shards.
- Rollout tie-in: use staged rollouts and feature flags to limit blast radius; run canary E2E before full release.
Trade-offs
- Full device E2E is slow/costly; mitigate with targeted smoke tests on PRs and more exhaustive nightly runs.
- Recordings speed up reproducibility but may drift—maintain periodic re-recording and contract tests.
This strategy balances speed, realism, determinism, and CI reliability for mobile networked features.