Location Services Testing Checklist (2026)
Location Services Testing Checklist (2026)
Location Services Testing Checklist (2026)
Location Services Testing Checklist (2026): Happy Path Scenarios
Location services are a core feature in many mobile and web applications, enabling maps, geofencing, proximity alerts, and location‑based personalization. Testing the happy path ensures that the basic flow—acquiring a location, using it in the UI, and persisting it when needed—works reliably across devices, OS versions, and network conditions. Below is a detailed, check‑by‑check list you can follow manually or embed in an automated test suite.
1.1 Permission Grant Flow
- Test: Launch the app for the first time; verify that the system location permission dialog appears (Android:
ACCESS_FINE_LOCATIONorACCESS_COARSE_LOCATION; iOS:NSLocationWhenInUseUsageDescription). - Pass criteria: Dialog shows correct rationale text; tapping Allow grants permission and the app proceeds to the next screen; tapping Deny leads to a graceful fallback UI (see error handling section).
- Example: On Android API 33, use
adb shell pm grant com.example.app android.permission.ACCESS_FINE_LOCATIONto pre‑grant and then observe that no dialog appears.
1.2 Location Acquisition Accuracy
- Test: With permission granted, trigger a location request (e.g., tap “Find My Location”).
- Pass criteria: The app receives a location within 5 seconds on Wi‑Fi, 10 seconds on cellular, and displays coordinates accurate to within 10 meters of a known reference point (use a GPS simulator or a known test fixture).
- Example: In Android Studio’s Emulator Extended Controls, set latitude = 37.7749, longitude = ‑122.4194 (San Francisco) and confirm the UI shows “You are in San Francisco, CA”.
1.3 Map Rendering and Marker Placement
- Test: After location is obtained, verify that the map centers on the coordinate and drops a marker at the exact point.
- Pass criteria: Map camera moves smoothly; marker icon aligns with the coordinate; tapping the marker opens an info window with the address derived from reverse‑geocoding (if applicable).
- Example: Use Espresso idling resource to wait for
onMapReadycallback, then assertGoogleMap.getCameraPosition().target.latitude == 37.7749.
1.4 Geofence Entry/Exit Events
- Test: Define a circular geofence of 50 m radius around the acquired location; walk (or simulate) outside the boundary and back in.
- Pass criteria: The app receives
GEOFENCE_TRANSITION_ENTERandGEOFENCE_TRANSITION_EXITcallbacks within 2 seconds of crossing the boundary; UI shows a toast or notification matching the event type. - Example: Using the Android
LocationTestUtilclass, calladdMockGeofence(LatLng, 50)and thensendLocationUpdate(LatLng outside)to trigger exit.
1.5 Location‑Based Feature Activation
- Test: If the app offers a feature like “Nearby Offers”, verify that after location fix the feature populates with data from the backend.
- Pass criteria: Network request includes latitude/longitude as query parameters; response renders at least one item; UI shows a loading spinner while waiting and hides it on success/failure.
- Example: Intercept the request with
MockWebServerand enqueue a JSON payload containing two offers; assert that RecyclerView displays two rows.
1.6 Background Location Updates
- Test: Enable background location (if supported) and send the app to the background; simulate movement and confirm that location callbacks continue.
- Pass criteria: The app receives at least one location update every 15 minutes (or as configured) while in background; battery impact stays within the threshold defined by the OS (e.g., < 1 % per hour on Android 12+).
- Example: Use
adb shell cmd appops setto whitelist background GPS, then run a script that changes the mock location every 30 seconds and logs timestamps fromLEGACY_GPS allow LocationCallback.
1.7 Handling of Mock Location Settings
- Test: Enable developer mock location on the device, select a mock app (e.g., Fake GPS), and set a location far from the real one.
- Pass criteria: The app respects the mock location if it has
ACCESS_MOCK_LOCATIONpermission; otherwise, it ignores the mock and continues to use the real location or falls back to the last known good fix. - Example: Grant
ACCESS_MOCK_LOCATIONto a test harness, then verify via logcat thatLocationProviderreportsmock=true.
1.8 Fallback to Network or Wi‑Fi Location
- Test: Disable GPS (via Settings → Location → Use location → Off) while keeping Wi‑Fi and mobile data on; trigger a location request.
- Pass criteria: The app receives a location derived from network/Wi‑Fi within 10 seconds; accuracy is lower (typically 50‑200 m) but sufficient for city‑level features.
- Example: On iOS, disable
Location Services → System Services → GPSand confirm thatCLLocationManagerstill returns a coordinate withhorizontalAccuracy > 50.
1.9 Location Persistence Across Sessions
- Test: After a successful fix, close the app, relaunch, and check whether the last known location is displayed (if the app caches it).
- Pass criteria: On restart, the UI shows the cached location with a stamp indicating “last updated < 5 min ago”; if cache is stale (> 30 min), the app requests a fresh fix.
- Example: Use SharedPreferences to store latitude/longitude; on launch read them and assert they match the values saved after the previous fix.
1.10 Multi‑Modal Location Sources (Fused Provider)
- Test: On Android, enable the Fused Location Provider; simulate GPS drift and Wi‑Fi jumps; observe that the provider smooths the output.
- Pass criteria: The reported location jumps less than 5 meters between consecutive updates when the underlying raw signals vary by > 20 meters.
- Example: Use the
LocationCallbackto log each update; compute distance between successive points and assert the max delta < 5 m over a 30‑second window.
---
Location Services Testing Checklist (2026): Error Handling and Edge Cases
Even when the happy path works, real‑world usage triggers error conditions that must be handled gracefully. This section enumerates the most common failure modes, edge/boundary values, and concurrency scenarios you should verify.
2.1 Permission Denied Scenarios
- Test: User taps Deny on the system permission dialog; alternatively, pre‑deny via
adb shell pm revoke. - Pass criteria: App displays a clear inline message (e.g., “Location access is required to show nearby places”) with a button that redirects to system settings (
ACTION_APPLICATION_DETAILS_SETTINGS). - Example: Espresso test:
onView(withId(R.id.location_denied_banner)).check(matches(isDisplayed())).
2.2 Permission Permanently Denied (Never Ask Again)
- Test: User selects Deny and checks “Don’t ask again”; then relaunch the app.
- Pass criteria: No permission dialog appears; the app shows a permanent denial banner and provides a direct link to settings.
- Example: On iOS, check
CLLocationManager.authorizationStatus == .deniedand verify UI state.
2.3 Location Services Disabled Globally
- Test: Turn off the device’s location master switch (Android Settings → Location → Off; iOS Settings → Privacy → Location Services → Off).
- Pass criteria: App detects the disabled state immediately (via
LocationManager.isProviderEnabledorCLLocationManager.locationServicesEnabled) and shows a prompt to enable it, without crashing. - Example: Use
adb shell settings put secure location_providers_allowed -gpsto disable GPS only; ensure app still works via network fallback.
2.4 No Network Connectivity
- Test: Enable airplane mode (or disable Wi‑Fi/mobile data) while GPS is on; request a location.
- Pass criteria: If GPS is available, a fix is still obtained (though possibly slower); if GPS is off, the app shows an offline banner and queues the request for retry when connectivity returns.
- Example: Use
adb shell svc wifi disable && adb shell svc data disableand assert that aLocationCallbackstill fires after ~10 seconds (GPS only).
2.5 GPS Signal Loss (Indoor/Tunnel)
- Test: Simulate loss of GPS by providing a static location for 30 seconds, then sending an empty location update (
nulllatitude/longitude). - Pass criteria: App does not crash; it either retains the last known good location with a “signal lost” indicator or falls back to network location after a timeout (e.g., 20 seconds).
- Example: In the emulator, open Extended Controls → Location → Set point → then click “Stop GPS” to simulate loss; monitor logcat for
LocationProviderstatus changes.
2.6 Stale Cached Location
- Test: Force the location cache to be older than the app’s staleness threshold (e.g., 45 minutes) by setting the system clock forward or by injecting a old timestamp via mock location.
- Pass criteria: App discards the stale cache and initiates a fresh location request; UI shows a loading spinner until the new fix arrives.
- Example: Use
adb shell date +%s -s "$(( $(date +%s) + 3000 ))"to jump 50 minutes ahead, then trigger a location request and verify a new update appears.
2.7 Rapid Successive Location Requests (Throttling)
- Test: Trigger location updates every 200 ms via a test harness while the app requests updates every 5 seconds.
- Pass criteria: The app respects the minimum interval set by the location request (e.g.,
setInterval(5000)) and does not flood the system with more than the allowed rate; battery impact stays low. - Example: Count callbacks in
LocationCallbackover 10 seconds; assert count ≤ 3 (for 5 s interval).
2.8 Concurrent Location Requests from Multiple Modules
- Test: Two different features (e.g., map and weather) request location simultaneously with different priorities (PRIORITY_HIGH_ACCURACY vs PRIORITY_LOW_POWER).
- Pass criteria: The fused provider merges requests and delivers updates at the highest requested accuracy; each consumer receives the same location object.
- Example: Register two
LocationCallbacks; verify that both receive identicalLocationinstances (same timestamp and coordinates) within 5 ms.
2.9 Location Permission Runtime Change (While App in Foreground)
- Test: While the app is visible, go to Settings → Apps → [Your App] → Permissions and toggle location off/on.
- Pass criteria: App receives a callback (
onPermissionChangedor similar) and updates UI immediately (e.g., hides map or shows permission rationale). No crash or frozen UI. - Example: Use Android’s
AppOpsManagerto listen forOPSTR_GPSchanges and assert that a LiveData object updates within 1 second.
2.10 Mock Location Detection Evasion
- Test: Run a known mock location app that attempts to hide its mock status (e.g., by clearing
isFromMockProvider). - Pass criteria: If the app has
ACCESS_MOCK_LOCATION, it should still detect the mock viaLocation.isFromMockProvider(); if not, it should ignore the bogus coordinates and either use the last good fix or request a new one. - Example: In a unit test, create a
Locationwithmock=trueand pass it to the location handler; assert that the handler logs a warning and does not update UI.
2.11 Boundary Values for Accuracy and Distance Filters
- Test: Set the smallest acceptable accuracy (
setSmallestDisplacement(0)) and the largest (setSmallestDisplacement(Integer.MAX_VALUE)) to verify the app does not reject extreme values. - Pass criteria: The app accepts the values without throwing
IllegalArgumentException; behavior matches expectations (zero displacement yields every update, max displacement effectively disables updates). - Example: Use reflection to call
LocationRequest.setSmallestDisplacement(0)and verify thatLocationCallbackfires for every simulated location change.
2.12 Handling of Null or Malformed Location Objects
- Test: Inject a
Locationinstance with latitude = 0.0, longitude = 0.0, accuracy = 0.0, or withtimeset to a future timestamp. - Pass criteria: The app validates each field; if any required field is invalid (e.g., accuracy ≤ 0), it discards the update and logs an error, but does not crash.
- Example: In a mock
LocationProvider, returnnew Location("gps") { { setLatitude(0); setLongitude(0); setAccuracy(0); } }and assert that the UI shows “Unable to determine location”.
2.13 Time Zone Changes Triggered by Location
- Test: Move the simulated location across a time zone boundary (e.g., from UTC‑8 to UTC‑7) while the app is running.
- Pass criteria: If the app displays local time based on location, it updates the displayed time within 5 seconds of the zone change; otherwise, it leaves time unchanged (explicitly documented).
- Example: Use
adb shell setprop persist.sys.timezone America/Los_Angelesthen change toAmerica/Denverand verify that aTextViewshowing local time updates accordingly.
2.14 Battery‑Optimization Interference (Doze, App Standby)
- Test: Force the device into Doze mode (
adb shell dumpsys deviceidle force-idle) while background location is enabled. - Pass criteria: The app continues to receive location updates at the frequency defined for high‑priority requests (or is granted a temporary whitelist if it holds the
ACCESS_BACKGROUND_LOCATIONpermission). - Example: After forcing idle, wake the device with
adb shell input keyevent KEYCODE_WAKEUPand check logcat for location timestamps spaced as expected.
2.15 Simulated GPS Spoofing Attack
- Test: Use a rooted device or emulator to feed deliberately incorrect coordinates (e.g., moving the user 10 km away from true location) to test anti‑spoofing logic.
- Pass criteria: If the app implements a sanity check (e.g., maximum speed > 200 km/h flagged as suspicious), it either discards the update or prompts the user to confirm the location.
- Example: Send location updates jumping from (37.7749,‑122.4194) to (37.7749,‑112.4194) within 2 seconds; assert that the app logs “Implausible speed detected” and does not update the map.
---
Location Services Testing Checklist (2026): Accessibility, Security, and Performance
Location features intersect with accessibility, privacy, and performance concerns. This section consolidates checks that ensure the implementation is usable by all individuals, respects user data, and does not degrade device performance.
3.1 Accessibility Labels for Location‑Related Controls
- Test: Use TalkBack (Android) or VoiceOver (iOS) to navigate to the “Find My Location” button, the permission rationale dialog, and any toast or snack‑bar that shows location status.
- Pass criteria: Each element announces a descriptive label (e.g., “Find my current location, button”) and states its current state (enabled/disabled, selected).
- Example: Run
adb shell uiautomator dump /sdcard/window.xmland verify that the button’scontent-descattribute contains “Find my current location”.
3.2 Contrast and Touch Target Size
- Test: Verify that map pins, the “Refresh location” icon, and any location‑status badges meet WCAG AA contrast (≥ 4.5:1) and have a minimum touch target of 48 dp.
- Pass criteria: Automated contrast checker (e.g., Android’s
AccessibilityTestFramework) returns no violations; UI inspector shows touch targets ≥ 48 dp × 48 dp. - Example: Use the
axe-androidlibrary in an Espresso test to asserthasNoViolations()for the map fragment.
3.3 Screen Reader Announcement of Location Updates
- Test: When a new location fix arrives, ensure that the change is announced to screen‑reader users without being overly verbose.
- Pass criteria: The announcement includes the place name (if reverse‑geocoded) and the accuracy (e.g., “You are near Market Street, accuracy 12 meters”). No announcement occurs if the location hasn’t changed significantly (> 5 m).
- Example: Use
AccessibilityEventcapture in a test and assert that the event text contains the expected string and that the event type isTYPE_VIEW_FOCUSED.
3.4 Support for Reduced Motion
- Test: Enable the system “Reduce motion” option; verify that map camera animations (e.g., pan to new location) either disable or use a non‑animated fallback.
- Pass criteria: No sudden jumps; the map still centers correctly but without motion effects that could trigger vestibular discomfort.
- Example: On iOS, check
UIAccessibility.isReduceMotionEnabledand assert that the map’scamera.animateTocall is replaced withcamera.moveTo.
3.5 Permission Rationale Accessibility
- Test: When the app shows a custom rationale dialog before requesting permission, ensure that the dialog is accessible: focus is trapped, all controls are labeled, and dismissing the dialog returns focus to the element that triggered it.
- Pass criteria: TalkBack reads the rationale text; focus order is logical; pressing ESC or back returns to the invoking button.
- Example: Use Espresso’s
isFocusable()andperform(pressBack())to validate focus restoration.
3.6 Data Minimization and Purpose Limitation
- Test: Inspect network traffic (via
adb shell tcpdumpor Charles Proxy) to confirm that only latitude, longitude, and optionally accuracy are sent to the server; no extra identifiers (e.g., device ID, IMEI) are included unless strictly necessary and disclosed. - Pass criteria: Request payload contains at most
lat,lng,accuracy,timestamp; any additional fields are justified in the privacy policy. - Example: Set up a mock endpoint that logs received JSON; assert that the parsed object has exactly those four keys.
3.7 Secure Transmission of Location Data
- Test: Verify that location‑sending endpoints use HTTPS with TLS 1.2 or higher; check that certificate validation is enforced (no acceptance of self‑signed certs in production builds).
- Pass criteria: Network security config indicates
cleartextTrafficPermitted="false";curl -v -k https://example.com/locationfails with certificate error unless-kis used. - Example: Run
adb shell cmd netlog set-trace-mode 1and inspect the log forTLSv1.3handshake.
3.8 Location Data Retention Policy
- Test: After a location fix is used (e.g., to show a nearby offer), confirm that the raw coordinates are not persisted longer than needed unless the user opts‑in to history.
- Pass criteria: Database query shows no entry for latitude/longitude after the feature’s TTL expires (e.g., 24 hours); if history is enabled, entries are encrypted at rest.
- Example: Query Room database:
SELECT * FROM location_log WHERE timestamp < :and assert zero rows after the cleanup job runs.
3.9 Background Location Battery Impact
- Test: Run the app with background location enabled for one hour on a fully charged device; measure battery drain using
adb shell dumpsys batterystats. - Pass criteria: Background location consumes ≤ 2 % of total battery per hour on a mid‑range device (adjust per OEM guidelines).
- Example: Compare
batterystatsbefore and after the test; compute(drain_after - drain_before) / battery_capacity.
3.10 Location‑Based Rate Limiting to Prevent Abuse
- Test: Simulate a malicious user sending location updates at the maximum possible rate (e.g., every 100 ms) via a rooted device.
- Pass criteria: Server (or local validation) throttles requests to a safe ceiling (e.g., one per 5 seconds) and responds with HTTP 429 if exceeded; client backs off and retries with exponential delay.
- Example: Use
OkHttpinterceptor to count requests; assert that after 6 rapid calls, the 7th receives a 429 response and the interceptor waits before retrying.
3.11 Auditing and Logging of Location Access
- Test: Enable the system’s “Show location access in status bar” (Android 12+) or the iOS privacy indicator; confirm that the icon appears whenever the app accesses location.
- Pass criteria: Icon shows in status bar for each foreground or background access that lasts > 5 seconds; disappears when access stops.
- Example: Use
adb shell cmd appops getto read the timestamp of the last access and compare with UI indicator timing.LEGACY_GPS
3.12 Handling of Location Data in Screenshots or Screen Recording
- Test: Take a screenshot while the map shows a precise location pin; verify that the image does not inadvertently expose exact coordinates in metadata (e.g., EXIF GPS tags).
- Pass criteria: Screenshot file’s GPS strip is empty or contains only approximate city‑level data if the app deliberately strips it.
- Example: Run
exiftool screenshot.pngand confirm thatGPS LatitudeandGPS Longitudetags are absent.
3.13 Localization of Location‑Related Strings
- Test: Switch device language to a right‑to‑left locale (e.g., Arabic) and ensure that location‑specific text (e.g., “You are here”) flows correctly and map UI mirrors appropriately.
- Pass criteria: Text alignment follows RTL rules; map controls (e.g., zoom buttons) are mirrored; no clipped strings.
- Example: Use
adb shell setprop persist.sys.language ar &&adb shell setprop persist.sys.country EGthen relaunch app and run UI Automator test for string visibility.
3.14 Performance of Geofence Registration
- Test: Register 100 geofences (the platform limit) and measure the time taken for the system to acknowledge all registrations.
- Pass criteria: Registration completes within 2 seconds; no
GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLEerrors. - Example: Loop to add
Geofence.Builder().setRequestId("fence_"+i)...build()and useGeofencingRequest.Builder(); addOnSuccessListener logs elapsed time.
3.15 Graceful Degradation When Location Is Unavailable
- Test: Disable all location providers (GPS, Wi‑Fi, cellular) and attempt to start a location‑dependent flow (e.g., “Find nearest store”).
- Pass criteria: App shows a clear offline state, offers a manual entry (zip code or city name), and does not crash or loop endlessly.
- Example: Use
adb shell svc location disableto turn off all providers; then trigger the flow and assert that a Snackbar with “Location unavailable” appears.
---
Leveraging Autonomous Exploration (SUSA) for Location Testing
SUSA (SUSATest) is an autonomous QA platform that explores an app without pre‑written scripts. It can generate a large portion of the location services checklist automatically, reducing manual effort while still providing deep coverage.
How SUSA Approaches Location Testing
When you point SUSA at an APK or a web URL, its agent treats location as any other sensor input. It:
- Requests permissions automatically, trying both grant and deny paths.
- Injects mock locations via the platform’s mock‑location API (Android) or via overriding
CLLocationManager(iOS) to simulate a grid of coordinates (city centers, borders, indoors/outdoors). - Triggers geofence entry/exit by moving the mock location across predefined radii.
- Tests background location by backgrounding the app and continuing to feed location updates.
- Checks error handling by toggling system location switches, enabling airplane mode, and forcing GPS loss.
- Validates accessibility by running TalkBack/VoiceOver checks on location‑related UI elements.
- Monitors network for location payloads, ensuring HTTPS and minimal data transmission.
- Measures performance by logging timestamps of location callbacks and computing jitter and battery impact via
dumpsys batterystats.
What Susa Covers Automatically
| Checklist Area | Items Covered by SUSA | Manual Gap |
|---|---|---|
| Happy Path | Permission grant, location acquisition, map centering, geofence callbacks, background updates | Verify exact UI text for edge‑case messages (e.g., “signal lost”) |
| Error Handling | Permission denied, services disabled, airplane mode, GPS loss, stale cache, rapid requests | Verify custom error dialogs and user‑flow recovery (e.g., manual zip entry) |
| Accessibility | Labels, contrast, touch target size, screen‑reader announcements, reduce‑motion support | Verify custom accessibility announcements that rely on app‑specific logic |
| Security/Privacy | HTTPS enforcement, data minimization, permission usage indicators, mock‑location detection | Verify server‑side retention policies and encryption at rest |
| Performance | Background battery drain, update frequency adherence, geofence registration time | Verify long‑term battery impact over multiple charge cycles and thermal throttling |
Running a Location‑Focused SUSA Session
# Install the CLI agent (once)
pip install susatest-agent
# Point at your APK; enable location mocking and set a test grid
susatest run \
--app myapp.apk \
--location-mode mock \
--location-grid "37.7749,-122.4194;34.0522,-118.2437;40.7128,-74.0060" \
--background-location true \
--accessibility-checks true \
--network-inspect true \
--output-dir ./susa-location-report
The command tells SUSA to:
- Mock locations at three major US cities (you can extend the grid as needed).
- Simulate background location by backgrounding the app every two minutes.
- Run accessibility audits (TalkBack) on every screen that shows a location button.
- Capture all HTTP(S) requests to validate that location data is sent securely and sparingly.
After the run, you’ll find an HTML report with sections titled Location Permissions, Geofence Events, Background Updates, and Privacy & Security, each containing pass/fail verdicts, screenshots, and raw logs.
Complementing SUSA with Manual Checks
While SUSA covers the majority of the checklist, certain nuanced scenarios still benefit from human insight:
- Verifying that a custom “location‑unavailable” fallback UI matches brand guidelines.
- Confirming that location‑based accessibility announcements are concise and not overly chatty.
- Performing exploratory testing in real‑world environments (e.g., underground parking, dense urban canyon) where GPS multipath causes atypical behavior.
- Reviewing server‑side logs for compliance with data‑retention policies (outside the scope of the client agent).
By using SUSA for the repetitive, sensor‑driven portions of the checklist and reserving manual effort for UX‑specific and policy‑driven checks, you achieve both efficiency and thoroughness.
---
Manual Test Techniques and Tooling
Even with autonomous assistance, a solid manual testing foundation helps catch edge cases that simulators may miss. Below are practical techniques, command‑line snippets, and tool recommendations for each checklist area.
4.1 Permission Flows
- Grant/Revoke via ADB:
# Grant
adb shell pm grant com.example.app android.permission.ACCESS_FINE_LOCATION
# Revoke (simulate deny)
adb shell pm revoke com.example.app android.permission.ACCESS_FINE_LOCATION
Simulate Location → Custom Location in Xcode’s Debug menu, then toggle Privacy → Location Services in Settings.4.2 Mock Location Injection
- Android Emulator: Open Extended Controls → Location → Manual tab → enter lat/lng → click Set Point.
- Command line:
adb shell am broadcast -a com.mock.location.intent.action.SET \
-e latitude 37.7749 -e longitude -122.4194 -e accuracy 10
(Requires a test‑app that registers a broadcast receiver; many open‑source mock location apps provide this.)
- iOS Simulator:
xcrun simctl location booted set 37.7749 -122.4194.
4.3 Geofence Testing
- Android: Use
GeofenceTestUtilfrom the Android location samples; it providesaddGeofence(LatLng, float radius)andremoveAllGeofences(). - iOS: Use
CLLocationRegionwithstartMonitoring(for:)and then change the simulated location viasimctl location.
4.4 Network Simulation
- Android:
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