How to Test Location Services in Mobile Apps (2026)
Location is one of the most sensitive permissions a user grants. It is also one of the most failure-prone features: GPS drift, permission edge cases, battery drain, background vs foreground, iOS vs An
Location is one of the most sensitive permissions a user grants. It is also one of the most failure-prone features: GPS drift, permission edge cases, battery drain, background vs foreground, iOS vs Android differences. This guide covers the test matrix.
Permission flows
- Location requested at feature use, not app launch
- Rationale clear before OS prompt
- Foreground-only permission offered first where possible
- Background permission requested separately with explicit justification
- Location-always (iOS) only requested when truly needed
- Approximate vs precise (Android 12+) choice respected
Location accuracy
- Feature works on approximate location (~100m)
- Feature requires precise only when necessary
- Accuracy degrades gracefully in poor GPS conditions
- Last-known location used as fallback when fresh fix unavailable
- Location-unavailable state shows clear UX ("Getting location...")
Foreground behavior
- Location updates while feature is visible
- Tracking pauses when feature exits (battery)
- Re-engages when feature re-enters
- Foreground frequency matches use case (1/sec for nav, 1/min for check-in)
Background behavior
- Background location use case visible to user
- Background updates at low power mode
- Geofence triggers fire reliably
- Background location pauses when app force-closed (Android 12+)
- Foreground service notification present if background location active
GPS edge cases
- Cold GPS → first fix within 30 seconds
- Indoor → degrades to cell / Wi-Fi fix
- Tunnel / underground → last-known with staleness indicator
- GPS spoof detected (if security-critical)
- Airplane mode → location disabled, clear message
- Mock location (dev option) detected
Battery
- Location updates at lowest useful frequency
- No continuous polling — use FusedLocationProvider (Android) or CoreLocation's efficient APIs (iOS)
- No background location if feature is not active
- Sleep / idle detection
iOS specifics
NSLocationWhenInUseUsageDescriptionand related plist entries set- Always authorization only after user has used feature with when-in-use first
- Precise vs reduced accuracy toggle handled (iOS 14+)
- Location arrow indicator visible in status bar when active
Android specifics
ACCESS_FINE_LOCATIONvsACCESS_COARSE_LOCATIONcorrectly requestedACCESS_BACKGROUND_LOCATIONrequested separately (Android 10+)- Foreground service type
locationdeclared - Battery optimization exemption requested only with strong justification
Edge cases
- Location permission granted then system-wide location disabled → handled
- Airplane mode then back online → location resumes
- Cell-only device (no GPS) → Wi-Fi and cell triangulation used
- Multi-user device (work profile) → per-user permission
- Timezone / DST edge cases for location-based time features
- User changes location provider priority → respected
Accessibility
- Current location announced by screen reader (e.g., "Centered on 123 Main St")
- Location-required CTAs clearly labeled
- Alternative (manual address entry) offered for denied users
Privacy
- Location not logged with user identifier unnecessarily
- Location not shared with third-party analytics at precise level
- User can export or delete location history
- Location rounded / obfuscated for display to other users
- No location in URL parameters
Manual testing
Use a physical device. Test in varied conditions:
- Outdoor with clear sky (fast GPS fix)
- Indoor with no Wi-Fi (slow or no fix)
- Moving at varied speeds
- Crossing geofence boundaries
- After airplane-mode toggle
- After device restart
Automated testing
Android
// Mock location
val provider = LocationManager.GPS_PROVIDER
locationManager.addTestProvider(provider, false, false, false, false, true, true, true, 0, 1)
locationManager.setTestProviderEnabled(provider, true)
val location = Location(provider).apply { latitude = 37.7749; longitude = -122.4194 }
locationManager.setTestProviderLocation(provider, location)
iOS
// Simulate a location in Xcode scheme: Edit Scheme → Run → Options → Default Location
// Or programmatically in UITests
How SUSA tests location
SUSA can fire mock-location intents on Android emulators and verify app behavior at multiple coordinates (airport, city, remote area). Personas:
adversarialtoggles location permission mid-useelderlychecks fallbacks when location is unavailablebusiness_professionalvalidates efficiency of location-dependent flows
susatest-agent test mapapp.apk --persona adversarial --location 40.7128,-74.0060
Common production bugs
- App freezes on cold start while waiting for first GPS fix
- Background location drains battery due to continuous high-accuracy updates
- Location permission prompted at launch before user understands use
- Location mismatch with timezone — app uses device timezone, backend assumes IP geolocation
- Stale location served from cache for minutes after user has moved
Location is sensitive, complex, and high-impact. Test every release. Real-device GPS testing is mandatory.
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