Mobile Development · Guide

Testing & Release

The test pyramid on a device, getting through app review, and finding out what is broken before your users tell you.

— min read Mobile Development

You Cannot Hotfix a Phone

A broken web deploy is reverted in minutes. A broken mobile release is a submission, a review queue, and then weeks of waiting while users update — some never will. That asymmetry is why mobile release discipline is stricter.

Three things follow from it: test more before shipping, roll out gradually so a bad build reaches few people, and instrument well enough that you learn about a crash from your dashboard rather than from a one-star review.

Unit & UI Tests

The pyramid holds, and the reason is speed. Unit tests run in seconds on the JVM or in a simulator; UI tests need a device, take minutes, and fail for reasons that have nothing to do with your code.

LayerCoversSpeed
UnitViewModels, mappers, business rulesMilliseconds
IntegrationRepository over a real local databaseSeconds
UICritical flows end to endMinutes, flaky
ManualFeel, gestures, real hardwareIrreplaceable

Architecture decides how much is testable. A ViewModel with injected dependencies and no framework types is a plain unit test; logic embedded in an Activity or a View needs a device to run at all.

UI tests fail for animation timing, keyboards, permission dialogs and network flakiness. Keep a small suite over the flows that must never break — a large flaky suite gets ignored, which is worse than not having one.

App Store Submission

Both stores review builds, and both reject for reasons that are policy rather than engineering. Read the guidelines before building the feature, not after the rejection.

Trips people upDetail
PaymentsDigital goods generally must use the store's billing, with its cut
Privacy disclosureDeclare every piece of data collected, including via SDKs
PermissionsEach one needs a clear justification string, asked in context
Account deletionIf you allow sign-up in the app, you must allow deletion in it
Sign-in optionsThird-party login may require offering a privacy-preserving one

Ship through the release channels rather than straight to everyone: internal testing, then a closed beta (TestFlight or a Play track), then a staged rollout — 1%, 10%, 50%, 100% — watching crash-free rate at each step, and halting the moment it dips.

Versioning is one-way. A released version code can never be reused, and users on a broken build are only rescued by a higher version — so the fix is always roll forward, never roll back.

Crash Reporting & Analytics

After release your visibility is whatever you instrumented. The baseline is a crash reporter with symbolicated stack traces, device and OS breakdown, and the app version attached — without symbols a crash report is a list of addresses.

WatchBecause
Crash-free sessionsThe one number that gates a rollout
ANRs / hangsA frozen app is a crash to the user, but is not reported as one
Cold start timeThe first thing every user experiences
Funnel drop-offWhere people give up — usually somewhere you never tested
Adoption per versionHow long the old broken build stays alive out there
Analytics is personal data. Declare it, honour tracking permission, avoid collecting anything you do not have a specific use for, and remember that an SDK's collection is disclosed under your name.

Feature flags are the closest thing to a hotfix you get. A risky feature behind a remote flag can be turned off in minutes instead of waiting out a review cycle.

Interview Questions

Why is mobile release riskier than web?

You cannot revert. A bad build needs a new submission, a review, and then users to update — some never do — so a defect lives on devices for weeks.

What is a staged rollout?

Releasing to a small percentage first and increasing it while watching crash-free rate. It limits the blast radius of a defect and gives you a signal before everyone has the build.

Why keep UI tests few?

They are slow and flaky — animations, keyboards, permission dialogs and network. A large flaky suite gets ignored, so cover only the flows that must never break.

What makes code testable on mobile?

Keeping logic out of framework types. A ViewModel with injected dependencies is a plain unit test; the same logic inside an Activity or View needs a device.

What are the common store rejection causes?

Bypassing store billing for digital goods, incomplete privacy disclosure, permissions without justification, and missing in-app account deletion when sign-up is offered.

Why do crash reports need symbols?

Release builds are optimised and stripped, so a raw trace is memory addresses. Uploading the symbol files at build time is what turns them back into readable stack traces.

Quick Quiz

1. A staged rollout primarily limits…
2. A released version code can be…
3. Most mobile tests should be…
4. Without uploaded symbols, a crash report shows…
5. The closest thing to a mobile hotfix is…