Skip to content
Bugwise
Menu
Mobile Testing

Install, Update and Uninstall

Fresh installs, upgrades, skipped versions, reinstalls and downgrades. Learn what happens to user data at each step, how to test upgrades, and why every bug report needs a version and build number.

35 min beginner Mobile

Monday, 8:05 a.m. A grocery delivery app ships version 3.0, a beautiful redesign. By 9:00 the support inbox is on fire: “I’ve been logged out”, “My saved shopping lists are gone!”, “Dark mode turned itself off”. The team had tested 3.0 for weeks, and every test passed. The catch? Every tester had installed 3.0 fresh. Nobody had started on 2.x, created real data, and then updated, which is exactly what millions of real users did that morning.

Most of your users will never do a fresh install of your newest version. They already have the app, with their account, favorites and settings, and they get the update in the background overnight. This lesson is about testing that journey.

Why it matters

  • Data loss is the worst kind of bug. A crash annoys people. Losing their saved addresses, order history or workout streak makes them leave and write one-star reviews.
  • It only shows up in one path. Upgrade bugs hide from testers who always start from a clean install. You have to deliberately walk the path from old version to new.
  • You can’t easily undo it. Once a broken update is out, the store won’t let users go back to the old version. A hotfix helps the next users, not the ones whose data is already gone.

That’s why teams do upgrade testingUpgrade testingChecking that updating from an older app version keeps the user's data and settings working.Open in glossary → before every releaseReleaseMaking a version of the software available to users.Open in glossary →, and why you should know exactly what happens to an app’s data when it’s installed, updated or removed.

Four ways an app lands on a phone

ScenarioWhat it meansWhat’s on the device beforeTypical risk
Fresh installThe app was never on this deviceNothingOnboarding, first permission prompts, empty states
Upgrade (update)A newer version replaces the old oneAll the old app dataData migration, staying signed in, settings kept
ReinstallUninstall, then install againUsually nothing, but some data can survive (see below)Leftover login, restored backups, “ghost” data
DowngradeAn older version replaces a newer oneData in a newer formatOld app can’t read new data: crashes, data loss

The first launch

The very first launch after a fresh install is the user’s first impression, and it’s packed with one-time logic: onboarding screens, sign-up or sign-in, and permission prompts.

  1. Onboarding. A few welcome screens that explain the app. Check you can skip them, that they appear only once, and that they don’t come back after an update or a restart.
  2. Permission prompts. On iOS, the system asks for each permissionApp permissionsThe user's approval for an app to use things like the camera, location, contacts or notifications.Open in glossary → only once. If the user taps “Don’t Allow”, the app can’t ask again; the user has to go to Settings. So timing matters: a good app explains why first (“Get delivery updates?”) and asks at the moment the feature is needed, not as five pop-ups on launch. On Android 13+ notifications also need a runtime permission.
  3. Empty states. No orders, no favorites, no history yet. Every list should have a friendly empty state, not a blank screen or a spinner that never stops.
  4. Sign in, then everything else. Check the first sync after sign-in: favorites from another device appear, and the app doesn’t show another user’s cached data.

What happens during an update

When a user updates, the system replaces the app’s code but keeps its data: the database, saved files, preferences and Keychain/Keystore items. The new code then has to make sense of data written by the old code. That’s where things go wrong.

Data migration

If version 2.0 stores favorites in a new database table, it needs a migration: code that runs on first launch after the update and converts the old data into the new format. Things to check:

Skipping versions

Not everyone updates every week. Some users go straight from 3.0 to 3.4, skipping three releases. If 3.2 added a migration and 3.4 assumes it already ran, those users break. Good apps run all missing migrations in order (3.0 → 3.1 → 3.2 → … → 3.4). Ask the developers which versions changed the data format, and test an upgrade from the oldest version still in use as well as from the previous one.

Forced updates (minimum version)

Sometimes an old version must stop working, for example because the server API changed. Apps then check a minimum supported version from the server and show an “Update required” screen. Test that:

  • Versions below the minimum see the prompt and can’t continue.
  • Versions equal to or above the minimum never see it. Watch out for 1.10 vs 1.9: compared as text, "1.10" comes before "1.9", so a lazy comparison thinks 1.10 is older.
  • The Update button opens the right store page.
  • There’s also usually a softer “Update available” prompt that can be dismissed. It shouldn’t nag on every launch.

What happens on uninstall

Uninstalling deletes the app’s sandbox: its database, files, caches and preferences. But “deleted” isn’t the whole story:

iOSAndroid
App files, database, preferencesDeletedDeleted
PermissionsReset (prompts show again)Reset
Secure storageKeychain items can survive a reinstallKeystore keys are deleted
Cloud backupiCloud backup restores data only when restoring a whole deviceAuto Backup can restore app data (up to 25 MB) when reinstalling with the same Google account
“Keep data” optionOffload App removes the app but keeps documents and dataSome apps offer “Keep app data” when uninstalling

On Android, the reverse surprise is Auto Backup: you uninstall, reinstall, and your old settings or even a stale login come back. That can be a feature (users love it) or a bug (restoring a token that the server already revoked). Know which one your team intends.

Try it: the version timeline

This is FreshCart, a grocery app with five releases. Play a real user’s journey:

  1. Install 1.0, go through onboarding, sign in, add a few favorites, and turn on Dark mode in Settings.
  2. Update to 1.1, then 1.9 (new database), then 2.0 (redesign). Check that everything survived.
  3. Reset, then do it again but skip straight from 1.0 to 2.0.
  4. Set the server’s minimum version to 1.9 and try different versions.
  5. Uninstall and reinstall. Watch the Keychain in the storage inspector.
  6. Try installing an older build over a newer one, and turn on Low storage before an update.

Check Settings › About for the version and build number, and keep an eye on the device log: it shows what the app does behind the scenes on every launch.

9:41

FreshCart is not installed

Pick a version on the timeline to install it.

Version timeline

  1. build 41
  2. build 48
  3. build 77
  4. build 83
  5. build 105

Nothing installed. Tap a version to install it.

Real stores only offer the newest version. Here you can pick any version to play users who update late, skip releases, or test older builds.

Storage inspector

App data

Deleted on uninstall

empty

Keychain

Can survive uninstall on iOS

empty

Permission

Notifications: not asked yet

Device log

  • Install a version to start…

Low storage and app size

Phones are often almost full. Updates need space for the download and the unpacked app at the same time, so they can fail even when the app itself is small.

  • The update fails cleanly. The old version stays installed and keeps working, with its data intact.
  • The app copes when storage is full at runtime. Saving a photo, downloading a playlist or writing to the database can fail. The user should see a clear message, not a crash or silently lost data.
  • App size is a feature. Check the size in the store listing and on the device (iOS: Settings › General › iPhone Storage › [app], Android: Settings › Apps › [app] › Storage). Watch for sudden jumps between versions, and for “Documents & Data” that keep growing forever (a cache that’s never cleared). iOS also asks for confirmation before downloading big apps over mobile data.

Store install vs test distribution

As a tester you’ll mostly install test builds, not store builds. They’re the same app, but not identical:

Store buildTest build (TestFlight, Firebase, Play testing tracks, Xcode, adb)
Who gets itEveryoneInvited testers
ServerproductionProductionThe live environment that real users use.Open in glossary →Often a stagingStagingA pre-release environment that mirrors production as closely as possible.Open in glossary → or test environmentEnvironmentA setup of servers, data and configuration where the software runs, such as dev, staging or production.Open in glossary →
Can install older versionsNoUsually yes
ExtrasNoneDebug menus, logging, sometimes a different icon or name

Before a release, make sure at least one upgrade test is done from the current store version to the release candidate, ideally on a real deviceReal deviceA physical phone or tablet used for testing, as opposed to an emulator or simulator.Open in glossary →. That’s the exact path your users will take. There’s more on beta channels in TestFlight and Firebase App Distribution.

Version and build numbers

Every app has two numbers, and you need both in every bug report.

2.4.1(318)
Major version
Big, possibly breaking change (redesign, new database)
Minor version
New features, still compatible
Patch version
Bug fixes only
Build number
Goes up with every build the team makes, even when the version stays the same

iOS: CFBundleShortVersionString (version) + CFBundleVersion (build) · Android: versionName + versionCode

  • Version (also “marketing version”) is what users see in the store, usually in semantic versioning style: MAJOR.MINOR.PATCH. 2.4.1 means the second big generation, fourth feature release, first bug-fix release.
  • Build number identifies one specific buildBuildA specific compiled version of the app or website that is ready to be installed or tested.Open in glossary →. The team may produce ten builds of version 2.4.1 while fixing bugs, and they all show 2.4.1. Only the build number tells them apart.
  • On Android, versionCode is an integer that must increase with every Play Store upload. Android refuses to install a lower versionCode over a higher one, which is why downgrades need special tools.

Exact

Build: FreshCart 2.4.1 (318), staging · iPhone 15, iOS 18.5 · upgraded from 2.3.0 (290)

Vague

Build: latest

“Latest” changes every day. A developer reading your report next week can’t know which code you tested, whether the fix was already in it, or whether the bug only happens after an upgrade. See Writing bug reports for the full template.

What to test

Fresh install

  • Onboarding appears once, can be skipped, and doesn’t return after restart.
  • Permission prompts appear in context, and the app works when they’re denied.
  • Empty states on every list; first sign-in syncs the right account’s data.

Upgrade

  • From the previous version, from the current store version and from the oldest supported version (skipped releases).
  • User stays signed in; favorites, carts, drafts, history and downloads are kept.
  • Settings and preferences keep their values.
  • Existing users don’t see first-launch onboarding again (a short “What’s new” is fine).
  • Update while the app is running in the background, and with a pending action (an item in the cart, an unsent message).

Forced and optional updates

  • Below / equal to / above the minimum version, including two-digit parts like 1.9 vs 1.10.
  • The Update button opens the right store page; the optional prompt can be dismissed and doesn’t nag.

Uninstall and reinstall

  • After reinstall the app behaves like a fresh install: no previous user’s name, token or data (unless restoring is an intended feature).
  • iOS: Keychain leftovers are cleaned up. Android: check what Auto Backup restores.

Edge cases

  • Low storage during install and update; storage full while using the app.
  • Downgrade with a test build (when the team supports it): clear error, no crash.
  • Update interrupted (network lost, phone restarted).

Common bugs

#BugWhat you seeTypical severity
1Logged out after updateSign-in screen right after updating; the token was moved or renamed without migratingHigh
2Data lost on upgradeFavorites, carts or history gone after updatingCritical
3Migration only from the previous versionWorks 3.3 → 3.4, loses data 3.0 → 3.4High
4Settings resetDark mode, language or units back to default after updateMedium
5Onboarding againExisting users see welcome screens and permission explanations againMedium
6Forced update loop“Update required” keeps showing after updating (string version compare)Blocker
7Crash on first launch after updateApp crashes once, or every time, because of unexpected old dataBlocker
8Ghost data after reinstallPrevious user’s name or token reappears after reinstallHigh (privacy)
9Update fails silentlyLow storage: no message, app half-updated or old data brokenMedium
10Cache that never shrinks“Documents & Data” grows by hundreds of MB over weeksLow–Medium

Find the bug

This build of FreshCart has six upgrade and install bugs. Use the timeline like a real user would: create data on an old version, then update, skip, restart, uninstall and reinstall. Compare what the app shows with the storage inspector and the device log.

🐞 Bug hunt: FreshCart upgrade paths

This demo has 6 hidden bugs. Explore it like a tester, then check your findings.

Found0/6
9:41

FreshCart is not installed

Pick a version on the timeline to install it.

Version timeline

  1. build 41
  2. build 48
  3. build 77
  4. build 83
  5. build 105

Nothing installed. Tap a version to install it.

Real stores only offer the newest version. Here you can pick any version to play users who update late, skip releases, or test older builds.

Storage inspector

App data

Deleted on uninstall

empty

Keychain

Can survive uninstall on iOS

empty

Permission

Notifications: not asked yet

Device log

  • Install a version to start…
  1. 1

    Hint: Sign in on 1.0, then update to any newer version.

  2. 2

    Hint: Turn on Dark mode and Weekly deals email on 1.0 or 1.1, then update to 1.9.

  3. 3

    Hint: Add favorites on 1.0, then update straight to 2.0. Compare with 1.0 → 1.9 → 2.0.

  4. 4

    Hint: Set the minimum version to 1.9, then update to the newest 1.x version.

  5. 5

    Hint: Finish onboarding on 1.x, then update to 2.0.

  6. 6

    Hint: Sign in, uninstall, then install again.

Tools and how-to

Upgrade test with TestFlight

  1. In the TestFlight app, open the app › Previous Builds and install the older build (or the current store version from the App Store).
  2. Use the app: sign in, create data, change settings.
  3. Install the new build from TestFlight without deleting the app. TestFlight installs it over the old one and keeps the data.

Simulator (from Xcode builds)

  • Install a build: xcrun simctl install booted OldFreshCart.app, then the new one the same way. Installing over an existing app keeps its data, just like an update.
  • Uninstall: xcrun simctl uninstall booted com.example.freshcart.
  • Erase everything (including the Keychain): Device › Erase All Content and Settings in the Simulator menu.

Check storage: Settings › General › iPhone Storage › [app] shows App Size and Documents & Data, plus Offload App and Delete App.

Upgrade test with adb

  1. adb install freshcart-1.0.apk, then use the app and create data.
  2. adb install -r freshcart-2.0.apk: -r replaces the app and keeps its data, exactly like an update.
  3. Downgrade (debuggable builds only): adb install -r -d freshcart-1.0.apk.

Clean up

  • Clear data without uninstalling: adb shell pm clear com.example.freshcart (or Settings › Apps › [app] › Storage › Clear storage).
  • Uninstall: adb uninstall com.example.freshcart.

Auto Backup: trigger a backup with adb shell bmgr backupnow com.example.freshcart, uninstall, and reinstall to see what gets restored.

Low storage: create an emulator in Android Studio’s Device Manager with small internal storage, or fill a test device with large files.

Example test cases

TC-UPG-001User stays signed in after updating from the store version

Preconditions

  • Current store version 2.3.0 (290) installed
  • User is signed in

Steps

  1. Install release candidate 2.4.0 (318) over the existing app
  2. Open the app

Expected result

Home screen opens without a sign-in prompt and shows the same account.

TC-UPG-002Favorites and settings survive an upgrade that skips versions

Preconditions

  • Version 2.0.0 (210) installed, user signed in

Steps

  1. Add 3 favorites
  2. Turn on Dark mode and set units to miles
  3. Update directly to 2.4.0 (318)
  4. Open Favorites and Settings

Expected result

All 3 favorites are listed; Dark mode is on and units are miles.

TC-UPG-003Existing users do not see onboarding after a major update

Preconditions

  • Version 1.10 installed and onboarding completed

Steps

  1. Update to 2.0
  2. Open the app
  3. Close and reopen the app

Expected result

No onboarding screens. A "What's new" sheet appears once and not after reopening.

TC-UPG-004Forced update compares two-digit version parts correctly

Preconditions

  • Server minimum version set to 1.9

Steps

  1. Open version 1.1: note the result
  2. Open version 1.9: note the result
  3. Open version 1.10: note the result

Expected result

1.1 shows "Update required". 1.9 and 1.10 open normally with no prompt.

TC-UPG-005Reinstall behaves like a fresh install

Preconditions

  • iOS device
  • User "Anna" is signed in

Steps

  1. Delete the app
  2. Install it again
  3. Open it

Expected result

Onboarding and sign-in screen are shown. No name, data or token from the previous user is visible.

TC-UPG-006Update with low storage fails without breaking the old version

Preconditions

  • Device has less free space than the update needs
  • Old version installed with data

Steps

  1. Start the update from the store or TestFlight
  2. Open the app after the failure

Expected result

The system shows a storage message; the old version still opens with all data.

Tip: click a test case to expand it.

Checklist

Install, update and uninstall checklist

0 of 11 checked

Check your understanding

Quick quiz

0/5 answered · 0 correct

  1. 1.All your tests pass on a fresh install of 3.0. Why can users still lose data after updating?

  2. 2.A migration works from 3.3 to 3.4 but loses data from 3.0 to 3.4. What is the most likely cause?

  3. 3.Why does "Update required" keep appearing on version 1.10 when the minimum is 1.9?

  4. 4.On iOS, which data can survive uninstalling and reinstalling an app?

  5. 5.What should the "Build" field of a bug report contain?

Key takeaways

  • Most users update, they don’t install fresh. Always test from an old version with real data to the new one.
  • After an update, check login, data, settings and onboarding, and test skipped versions, not just the previous one.
  • Forced updates must compare versions as numbers (1.10 is newer than 1.9).
  • Uninstall deletes the app’s data, but iOS Keychain items can survive and Android Auto Backup can restore data. A reinstall should feel like a fresh install unless restoring is intended.
  • Stores never downgrade; test builds can. Keep old builds around for upgrade testing.
  • Every bug report needs the version and build number, the device and OS, and the upgrade path when it matters.

Finished this page?Nice work, this page is complete!

Mark it as done to track your progress. It's saved in this browser, no account needed.

Its review cards are now in Bites ⚡
Esc

Type to search the whole site.