Mobile App Pre-Release Testing Checklist (2026)
A pre‑release checklist is the safety net that catches regressions before they reach users. In 2026 mobile apps ship faster than ever, with continuous delivery pipelines pushing updates multiple times
Motivation and Scope
A pre‑release checklist is the safety net that catches regressions before they reach users. In 2026 mobile apps ship faster than ever, with continuous delivery pipelines pushing updates multiple times a week. A single missed edge case—such as a permission denial that crashes the flow on a low‑end device—can generate thousands of one‑star reviews and trigger store penalties.
The checklist below is platform‑agnostic; it applies to Android, iOS, and cross‑platform frameworks (Flutter, React Native, Kotlin Multiplatform). Each area lists concrete pass criteria, the manual steps that validate them, and the automated techniques that can cover the same ground in one autonomous run. By following the guide you will reduce post‑release fire‑fighting, improve store ratings, and build confidence that every release meets a baseline of quality.
---
Functional Testing
Core user flows
Every release must verify that the primary journeys—login, signup, product browse, checkout, settings change—complete without blocking errors. Define a happy‑path script for each flow and assert that:
- All UI elements are interactable within 2 seconds of appearing.
- Expected navigation occurs (e.g., after successful login the app lands on the home screen).
- No toast, dialog, or snackbar remains on screen after the action finishes.
Edge case handling
Beyond the happy path, test:
- Invalid input (empty fields, malformed email, out‑of‑range numbers).
- Rapid successive taps (double‑submit protection).
- Interruptions such as incoming calls, screen rotation, or device lock during a flow.
- Background termination while a network request is pending.
Automation with SUSA
SUSA explores the app autonomously, generating a graph of reachable states and exercising each transition with a set of persona‑driven behaviors (curious, impatient, power user, etc.). When you upload an APK or point SUSA at a web URL, it:
- Records every distinct screen visited.
- Attempts to populate forms with valid and invalid data according to the persona’s tolerance for errors.
- Triggers system‑ Triggers dialogs, handles permission prompts, and follows deep links that appear in the UI.
- Marks a flow as PASS only if the final state matches the expected outcome (verified via image‑based or accessibility‑tree assertions).
Because SUSA does not rely on pre‑written scripts, it catches regressions that appear only when a new UI element changes the navigation tree—something a static test suite might miss.
Manual spot checks
Even with autonomous coverage, a tester should:
- Verify that custom animations do not block interaction (e.g., a modal that fades in over 500 ms but disables taps until the animation ends).
- Confirm that error messages are clear, actionable, and localized.
- Ensure that any “undo” or “cancel” option restores the previous state without data loss.
---
Install, Update, and Migration Testing
Fresh install
A clean install must:
- Launch within the platform‑specific startup time threshold (Android < 2 s, iOS < 1.5 s on a mid‑tier device).
- Show a valid onboarding flow or skip it if the user has opted out previously (checked via a flag stored in secure storage).
- Request only the permissions that are strictly necessary at first launch; any additional permissions must be justified by a clear purpose string.
Upgrade from previous version
When an existing version is upgraded:
- The app must not crash during the initial splash or while restoring shared preferences.
- Database schema migrations should run to completion without leaving the DB in an inconsistent state. Use a version‑number check in
onCreate/didFinishLaunchingand assert that the schema version matches the expected constant. - User‑generated content (photos, documents, game progress) must remain accessible; verify by opening a few random items after the upgrade.
Data migration and backward compatibility
If you introduce a new data format (e.g., moving from SQLite to Room, or changing a JSON schema):
- Provide a migration script that reads the old format, transforms it, and writes the new one.
- Log any conversion errors to a remote analytics endpoint (with user consent) for post‑release monitoring.
- Keep a fallback path that can read the old format for a grace period (two releases) in case a user skips an intermediate update.
Rollback scenario
In the event a hotfix is required, the app must be able to revert to the previous version’s behavior:
- Feature flags that gate new functionality must default to OFF when the flag service is unreachable or returns an error.
- Remote config values should have a safe hard‑coded fallback.
- Test the rollback by installing version N, updating to N+1, then forcing a downgrade to N (via adb/install or TestFlight) and confirming that data remains usable.
---
Permissions and Privacy
Runtime permission requests
Modern OSes require explicit consent for dangerous permissions. Verify:
- The app does not request a permission at launch unless it is needed immediately.
- Each request is accompanied by a rationale that explains why the permission is required and what the user gains by granting it.
- If the user denies, the app gracefully degrades (e.g., hides the camera button, shows a placeholder image) and does not crash.
Permission denial handling
Test both deny and deny + don’t ask again paths:
- After a denial, subsequent attempts to use the protected API should return a predictable error code or exception that the app catches and translates into a user‑friendly message.
- When the user selects “Don’t ask again,” the app should redirect to the system settings page with a clear call‑to‑action (e.g., “Go to Settings → Permissions → Enable Microphone”).
Privacy label alignment
Store privacy labels (Apple’s App Privacy Details, Google Play’s Data safety form) must reflect the actual data collected:
- Enumerate all data types gathered (identifiers, usage diagnostics, content, location).
- For each type, specify whether it is linked to the user’s identity and whether it is used for tracking.
- Cross‑check the enumeration against the codebase: search for analytics SDK initialization, file writes to external storage, network calls to known tracking endpoints.
Testing with SUSA
When SUSA runs a session, it simulates the adversarial persona that actively denies permissions and taps on misleading UI. The platform records:
- Whether the app crashes or shows an unhandled exception after a denial.
- If the app presents a settings shortcut when the user repeatedly tries to access a denied feature.
- Any network calls that still occur despite a denial (indicating a possible bypass).
These observations are exported as a JSON report that can be diffed against a baseline to spot regressions in permission handling.
---
Offline and Poor Network Conditions
Simulating network loss
Use the platform’s network‑conditioning tools:
- Android:
adb shell cmd netem set --loss 30% --delay 200msor the built‑in Network Speed tab in Android Studio Profiler. - iOS: Network Link Conditioner profile (e.g., “Lossy 3G”).
- CI: Docker containers with
tcrules or services like Toxiproxy.
Graceful degradation
When connectivity drops:
- Ongoing requests should be retried with exponential back‑off (initial delay 500 ms, max 5 s, jitter ±25 %).
- The UI must display a non‑intrusive indicator (e.g., a banner) that explains the issue and offers a retry button.
- Any optimistic updates (e.g., sending a message) should be stored locally and synchronized when the network returns.
Data sync after reconnect
After the network is restored:
- The app must resume paused uploads/downloads without duplicating data. Use idempotent keys or server‑side deduplication.
- Conflicts (local edit vs. server edit) should be resolved according to a documented strategy (last‑write‑wins, merge, or user prompt).
- Verify that the sync completes within a reasonable time (e.g., < 10 s for a 1 MB payload on a recovered 3G link).
---
Performance and Battery
Launch time, frame rate, jank
Measure cold and warm start:
- Cold start: kill the process, launch via launcher/home screen, timestamp until first frame is drawn. Target < 2 s on a Snapdragon 7‑gen 2 or equivalent.
- Warm start: launch from recent apps, target < 800 ms.
For frame rendering:
- Use
adb shell dumpsys gfxinfo(Android) or Instruments → Core Animation (iOS) to capture 90th‑percentile frame time. Aim for < 16 ms (60 fps) with < 5 % frames exceeding 16 ms.
CPU, memory, battery consumption
- CPU: average usage < 15 % during idle navigation, < 40 % during heavy list scrolling.
- Memory: steady‑state heap < 80 MB for typical screens; no unbounded growth after 10 minutes of interaction.
- Battery: run a 30‑minute scripted session (mix of UI interaction and idle) and record drain with Battery Historian (Android) or Energy Log (iOS). Target < 2 % per hour for a typical productivity app; games may tolerate higher drain but must stay below platform‑specific thresholds.
Profiling tools
- Android Studio Profiler, Xcode Instruments, or open‑source alternatives like Perfetto.
- Integrate automated checks in CI: fail the build if any metric exceeds the defined threshold.
Automated performance thresholds
Define a JSON performance baseline:
{
"coldStartMs": 1800,
"warmStartMs": 750,
"frame90thMs": 16,
"cpuIdlePct": 15,
"memMaxMb": 90,
"batteryDrainPctPerHr": 2
}
A CI step runs a short scripted workflow, extracts the metrics via adb shell dumpsys or xcrun simctl spawn, and compares against the baseline.
---
Accessibility (WCAG)
Touch target size, contrast, screen reader
- Minimum touch target: 48 dp (Android) / 44 pt (iOS). Verify with UI Automator or XCTest that every interactive element meets the size.
- Contrast ratio: ≥ 4.5:1 for normal text, ≥ 3:1 for large text. Use the Accessibility Scanner (Android) or AXCore (iOS) to automate contrast checks.
- Screen reader: ensure every view has an accessible label, hint, and (if applicable) a value. Test with TalkBack (Android) and VoiceOver (iOS) by navigating via swipe gestures and confirming that spoken output matches the visual intent.
Dynamic type support
- Verify that text scales correctly when the user increases font size in system settings (up to 200 % of default). Layouts must not truncate or overlap.
- Use
assertThat(view.getLineCount()).isGreaterThan(0)after scaling to ensure at least one line is visible.
Testing with accessibility scanner
Run the scanner as part of the unit test suite:
# Android
adb shell am instrument -w com.google.android.apps.accessibility.test/.AccessibilityTestRunner
# iOS (via fastlane)
fastlane run scan_test scheme:MyApp device:"iPhone 14"
Fail the build if any WCAG 2.1 AA violation is reported.
Manual checks
- Verify that custom gestures (e.g., pull‑to‑refresh) have an accessible alternative (button or menu item).
- Confirm that modal dialogs trap focus and return it to the triggering element upon dismissal.
- Ensure that any color‑coded status (e.g., red for error) is accompanied by an icon or text label.
---
Security Basics
Data storage encryption
- Sensitive data (tokens, passwords, health info) must be stored in the platform’s encrypted keystore (Android Keystore, iOS Keychain) or encrypted with a randomly generated key protected by the device’s passcode.
- Verify that no plain‑text secrets appear in logs, shared preferences, or
UserDefaults. Use a log‑cat filter to search for patterns likepasswordortoken.
Network security (TLS, certificate pinning)
- All network calls must use HTTPS with TLS 1.2 or higher.
- If pinning is employed, ensure the pins are updated before the certificate expires and that the app handles pin‑failure gracefully (shows an error, does not fall back to plain HTTP).
- Test with a man‑in‑the‑middle proxy (e.g., mitmproxy) and confirm that the app rejects connections when the proxy’s certificate is not trusted.
OWASP Mobile Top 10 quick checks
| # | Area | Quick verification |
|---|---|---|
| M1 | Improper Platform Usage | Check that intents with setComponent are not exposed without proper permission guards. |
| M2 | Insecure Data Storage | Scan for MODE_WORLD_READABLE or getExternalStorageDirectory() usage for sensitive files. |
| M3 | Insecure Communication | Verify that all domains in NetworkSecurityConfig use cleartextTrafficPermitted="false". |
| M4 | Insecure Authentication | Ensure that password‑based auth uses rate limiting and secure password hashing (argon2id, bcrypt). |
| M5 | Insufficient Cryptography | Confirm that any custom crypto uses established algorithms (AES‑GCM, RSA‑OAEP) and not ECB mode. |
| M6 | Insecure Authorization | Validate that backend endpoints check the JWT/token claims and scope. |
| M7 | Client Code Quality | Run static analysis tools (SpotBugs, SonarSwift) to catch hard‑coded secrets. |
| M8 | Code Tampering | Verify that the app checks its own signature at runtime (optional but recommended). |
| M9 | Reverse Engineering | Use ProGuard/R8 (Android) or Swift stripping (iOS) and confirm that symbols are obfuscated. |
| M10 | Extraneous Functionality | Ensure that debug flags, verbose logging, and test endpoints are stripped in release builds. |
Penetration testing lite
- Run a static analysis scan (MobSF, AndroBugs, OWASP ZAP in passive mode) on the APK/IPA.
- Perform a dynamic scan with a rooted/jailbroken device, installing a trusted CA and observing whether the app still validates certificates.
- Document any findings and assign a risk level; block release if any high‑severity issue remains.
---
Localization and RTL
Language switching
- The app must respect the system locale and allow an in‑app language picker that overrides it without requiring a restart.
- After switching, all visible strings (including those generated via formatting functions) must reflect the new language immediately.
Layout mirroring
- For right‑to‑left locales (Arabic, Hebrew, Urdu), verify that:
- Horizontal padding/margin values are swapped.
- Icons with directional meaning (e.g., “next” arrow) are mirrored automatically or replaced with an RTL‑specific asset.
- Scroll direction in
RecyclerView/ListViewfollows the reading order.
Date, number, currency formatting
- Use the platform’s
DateFormat,NumberFormat, andCurrencyFormatterAPIs; avoid hard‑coded patterns. - Test edge cases: right‑to‑left number shapes (Arabic-Indic digits), different decimal separators, and currency placement (prefix vs suffix).
Pseudolocalization
- Run a pseudolocale build (e.g.,
en-XA) that expands strings and adds bracketing characters. This reveals UI clipping and hard‑coded strings. - Automate the check: after launching the pseudolocale build, assert that no view’s width or height exceeds its parent by more than 5 %.
---
Push Notifications and Deep Links
FCM/APNs handling
- Register the device token with the backend on first launch and after token refresh callbacks.
- Verify that the app correctly parses the payload and displays a notification with the expected title, body, and action buttons.
- Test the data‑only payload scenario: the app should wake in the background, perform any silent work (e.g., sync), and not show a visible notification unless intended.
Notification actions
- If the notification includes action buttons (e.g., “Reply”, “Archive”), ensure that tapping them launches the correct foreground service or activity and passes the relevant extras.
- Verify that the app respects the notification category and that the actions are visible on the lock screen when the user has granted the appropriate permission.
Deep link routing
- Define a clear URI scheme or universal link pattern (e.g.,
myapp://product/12345orhttps://myapp.com/product/12345). - Test that tapping the link from a browser, another app, or a notification opens the correct screen and passes the ID as an argument.
- Verify the fallback behavior when the app is not installed: the user should be redirected to the Play Store/App Store or a web landing page.
Background vs foreground
- When the app is in the background and a push arrives, confirm that any heavy work is off‑loaded to a
WorkManager(Android) orBGTaskScheduler(iOS) to avoid ANR. - Ensure that UI updates triggered by a push (e.g., badge count) are performed on the main thread only after the app returns to the foreground.
---
Crash, ANR, and Stability Monitoring
Symbolication, crash reporting
- Integrate a crash‑reporting SDK (Firebase Crashlytics, Sentry, Instabug).
- Verify that native stacks are symbolicated for release builds (upload dSYMs for iOS, ProGuard mapping file for Android).
- After a test run, check the dashboard for new issue IDs and ensure that the crash signature includes the exact class/method and line number.
ANR detection
- Android: monitor the
anrtrace in/data/anr/or viaadb shell bugreport. - iOS: watch for the main thread being blocked > 2 seconds (watchdog termination).
- Automate detection by running a UI exerciser (e.g.,
adb shell monkey -p) and asserting that no-v 5000 ANRappears in the logs.
Stress testing with monkey
- Run a high‑event count monkey test with throttling to simulate real‑world usage:
adb shell monkey -p com.example.myapp -v 10000 --throttle 100 --pct-syskeys 0 --pct-nav 0 --pct-majornav 0 --pct-appswitch 0
- Capture the logcat and grep for
ANRorcrash. Fail the build if any are found.
Using SUSA for autonomous crash detection
During an autonomous exploration, SUSA records any uncaught exception or native signal that terminates the process. The resulting report includes:
- The exact screen and UI element that triggered the fault.
- A short video or screenshot sequence for reproduction.
- Classification (Java exception, native signal, ANR).
These findings can be uploaded directly to your crash‑reporting provider as a “test‑only” issue, allowing developers to triage before the release hits production.
---
Store Metadata and Privacy Labels
App description, screenshots, version notes
- The short description must be ≤ 80 characters and convey the core value proposition.
- Full description should avoid keyword stuffing; instead, focus on clear, benefit‑driven language.
- Screenshots must show the actual UI (no placeholders) and be localized for each store listing. Use automated tools like
fastlane supply(Android) orfastlane deliver(iOS) to verify that uploaded assets match the approved set.
Privacy label accuracy
- Cross‑check the store’s privacy form against the actual data accesses observed during a full exploratory run (SUSA can log every file write, keychain entry, and network endpoint).
- Any discrepancy must be corrected before submission; otherwise the app may be rejected or penalized post‑release.
Age rating, categorization, and content descriptors
- Ensure that the selected rating matches the highest maturity level of any content (e.g., violence, gambling, profanity).
- If the app includes user‑generated content, enable the appropriate “Interact Users” descriptor and confirm that moderation flows are in place.
---
Rollback and Hotfix Plan
Feature flags, remote config
- Every major change should be gated behind a flag that defaults to OFF.
- Use a remote‑config service (Firebase Remote Config, LaunchDarkly) to enable the flag for a small percentage of users (canary) before full rollout.
- Verify that the flag evaluation occurs early in the app lifecycle (before any UI that depends on it is inflated).
OTA updates, patching
- For critical bugs, consider an in‑app patch mechanism (e.g., CodePush for React Native, dynamic feature modules for Android).
- Test the patch flow:
- Simulate a server‑side flag that triggers a patch download.
- Confirm that the patch applies without requiring a restart (or with a controlled restart that preserves state).
- Validate that the patched behavior matches the intended fix and that no regressions are introduced.
Monitoring rollout
- Instrument key metrics (crash rate, ANR rate, core conversion funnel) with feature‑flag segmentation.
- Set up alerts: if the flagged group’s crash rate exceeds twice the baseline, automatically roll the flag back to OFF.
- Conduct a post‑mortem after each rollout: compare the actual metrics against the predicted impact and update the flag‑rollout playbook accordingly.
---
Consolidated Test Matrix
| Test Area | Pass Criteria | Manual Approach | Automated Approach | Primary Tools |
|---|---|---|---|---|
| Functional flows | All happy‑paths complete; error states handled | Scripted tester walks each flow, verifies UI & state | Persona‑driven exploration, assertion on final state | SUSA, Espresso/XCUITest, Appium |
| Install/Update/Migration | Clean launch < 2 s; DB migrations succeed; data intact after downgrade | Install via adb/TestFlight, verify on‑device | Automated device farm scripts, schema version checks | Firebase Test Lab, Gradle/ fastlane |
| Permissions & Privacy | Requests only when needed; denial handled gracefully; privacy label matches code | Tester denies each permission, observes UI | Adversarial persona denies & retries, logs network | SUSA, MobSF, ADB logcat |
| Offline/Poor Net | Requests retry with back‑off; UI shows indicator; sync recovers | Toggle airplane mode, use Network Link Conditioner | Scripted network‑loss/regain cycles, check local queue | Toxiproxy, Charles Proxy, Espresso idling resources |
| Performance/Battery | Launch < 2 s, 90th‑pct frame < 16 msec, battery drain < 2 %/h | Use Profiler/ Instruments, manually interact | CI job runs scenario, extracts metrics, compares to baseline | Android Studio Profiler, Xcode Instruments, Perfetto |
| Accessibility | Touch target ≥ 48 dp, contrast ≥ 4.5:1, screen‑reader labels present | Manual TalkBack/VoiceOver walk, measure with ruler | Automated scanner, dynamic‑type layout assertions | Accessibility Scanner, AXCore, Espresso accessibility checks |
| Security | Data encrypted at rest, TLS 1.2+, no clear‑text secrets, OWASP Top 10 cleared | Manual key‑chain inspection, MITM proxy test | Static analysis, dynamic taint, permission denial checks | MobSF, SonarQube, Mitmproxy, SUSA adversarial |
| Localization/RTL | Layout mirrors, strings update instantly, numbers/format correct | Switch language, inspect UI, use pseudolocale | Automated screenshot diff, layout‑assert tests | Fastlane screenshot, Lokalise, Espresso screenshot tests |
| Push/Deep Links | Notification shows correct payload; actions launch expected screen; deep link routes correctly | Send test push via console, click notification, verify UI | Automated FCM/APNs push, deep‑link intent launch, assert activity | Firebase Console, Xcode notification sim, adb am start |
| Crash/ANR/Stability | No uncaught exceptions, no ANR traces, symbolicated reports | Exercise app, check logcat for “ANR”, view crash dashboard | Monkey stress, Susa autonomous run, automatic symbolication upload | Firebase Crashlytics, Sentry, adb bugreport, SUSA |
| Store Metadata | Description, screenshots, privacy label accurate, age rating correct | Manual store listing review, compare to build | Automated metadata validation script, privacy‑label diff | Fastlane supply/deliver, custom CI script |
| Rollback/Hotfix | Feature flag safe default, remote‑config fallback works, patch applies cleanly | Toggle flag offline, observe behavior, apply patch via adb | Canary rollout simulation, automated health‑check queries | Firebase Remote Config, LaunchDarkly, CodePatch scripts |
---
Quick Reference Checklist
- [ ] Functional: All core flows pass; error states show helpful messages.
- [ ] Install/Update: Fresh install < 2 s; migration scripts run clean; downgrade preserves data.
- [ ] Permissions: Requests only when needed; denial shows graceful fallback and settings shortcut.
- [ ] Privacy Label: Matches observed data collection; no hidden tracking.
- [ ] Offline: Requests retry with exponential back‑off; UI shows non‑intrusive banner; sync recovers.
- [ ] Performance: Cold start < 2 s, 90th‑pct frame < 16 ms, battery drain < 2 %/h.
- [ ] Accessibility: Touch targets ≥ 48 dp/44 pt, contrast ≥ 4.5:1, screen‑reader labels present, dynamic type works.
- [ ] Security: Data encrypted, TLS enforced, no clear‑text secrets in logs, OWASP Top 10 cleared.
- [ ] Localization: Strings update instantly, layouts mirror for RTL, numbers/formats correct.
- [ ] Push/Deep Links: Notification payload parsed correctly; actions launch intended screens; deep links route with fallback.
- [ ] Crash/ANR: No uncaught exceptions or ANRs in stress tests; reports symbolicated.
- [ ] Store: Description, screenshots, privacy label, age rating accurate; assets match build.
- [ ] Rollback: Feature flag defaults OFF; remote‑config fallback works; patch applies cleanly.
---
Closing Takeaways
A disciplined pre‑release checklist transforms release anxiety into measurable confidence. By dividing the effort into well‑defined areas—functional integrity, install lifecycle, permissions, offline resilience, performance, accessibility, security, localization, push/deep links, stability, store metadata, and rollback readiness—you create a repeatable process that scales with team size and release frequency.
Leveraging autonomous exploration tools like SUSA amplifies coverage: a single run can exercise hundreds of UI paths, simulate varied user personas, and surface permission, crash, and ANR issues that would otherwise require large manual test suites. Combine this autonomous baseline with targeted manual checks for nuanced UX details, and you obtain a safety net that catches regressions before they reach users.
Invest the time to codify each criterion in your CI pipeline, store the results as version‑controlled artifacts, and treat any checklist failure as a blocker. The payoff is fewer hot‑fixes, higher store ratings, and a product that feels solid to every user, no matter their device, network, or ability. Ship with confidence, ship with quality.
Test Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free