How to Write Test Cases for Location Services (With Examples)

How to Write Test Cases for Location Services (With Examples)

April 22, 2026 · 16 min read · How-To Guides

How to Write Test Cases for Location Services (With Examples)

Location services are a core capability in many mobile and web applications, powering features such as navigation, geo‑fencing, location‑based recommendations, and emergency‑services integration. Because the underlying hardware (GPS, Wi‑Fi, cellular, or sensor fusion) behaves differently across devices, OS versions, and network conditions, a dedicated test‑case suite is essential to catch defects that generic functional tests miss. This guide walks you through the full lifecycle of creating high‑signal test cases for location services: from understanding the anatomy of a test case, through classification and matrix construction, to data setup, prioritization, automation, and real‑world production edge cases. Each section contains concrete examples, tables, and code snippets you can copy into your test repository today.

1. Understanding Location Services Testing

1.1 What Constitutes a Location Service

A location service is any software component that obtains, processes, or acts upon geographic coordinates. Typical sources include:

Testing must therefore cover not only the API contract (e.g., latitude/longitude values, accuracy, timestamp) but also the interaction with permission dialogs, background execution limits, and error‑propagation paths.

1.2 Why Dedicated Test Cases Matter

Location‑related bugs often surface only under specific combinations of:

A generic test that merely checks “the app shows a map” will miss crashes caused by null latitude values, ANRs triggered by continuous location callbacks, or privacy violations when the app ignores a denied permission. By writing explicit test cases you gain traceability to requirements, enable risk‑based prioritization, and create reusable assets for both manual execution and autonomous exploration platforms.

2. Anatomy of a Location‑Service Test Case

A well‑structured test case makes review, execution, and automation straightforward. The following elements are mandatory for location‑service testing.

2.1 Test‑Case ID and Title

2.2 Preconditions

List everything that must be true before the first step runs. For location services this often includes:

2.3 Test Steps

Numbered actions that the tester or automation script performs. Keep each step atomic and observable. Example steps for a GPS‑loss scenario:

  1. Enable mock GPS and set initial coordinate to (37.7749, -122.4194) with accuracy 5 m.
  2. Trigger the feature that starts location updates (e.g., press “Start Tracking” button).
  3. Wait 5 seconds to confirm steady updates.
  4. Change mock GPS signal to no fix (return LocationAvailability: false).
  5. Wait 12 seconds.
  6. Observe UI and logs.

2.4 Expected Result

A clear, measurable outcome. Avoid vague phrasing like “the app should work”. Instead, state:

2.5 Post‑conditions / Cleanup

Actions that return the device to a neutral state, preventing test bleed‑over:

3. Classification: Positive, Negative, Boundary, and Edge Cases

Organizing test cases by type helps you achieve balanced coverage and prioritize effort.

3.1 Positive Scenarios

These verify that the location service behaves correctly when everything functions as intended.

3.2 Negative Scenarios

These confirm the app handles invalid or missing data gracefully.

3.3 Boundary and Edge Cases

These push the system to its limits or explore uncommon states.

3.4 Fault‑Injection and Interruption Cases

Simulate real‑world interruptions to verify resilience.

4. Building a Test Matrix: 20+ Example Cases

Below is a concrete test matrix you can import into a test‑management tool. Each row includes an ID, preconditions, numbered steps, and the expected result. Feel free to adjust the values to match your app’s specific APIs.

IDPreconditionsStepsExpected Result
LOC‑001Device location mode = High accuracy; mock GPS enabled; app at home screen; location permission granted.1. Set mock GPS to (40.7128, -74.0060), accuracy 5 m.
2. Tap “Start Tracking”.
3. Wait 8 seconds.
4. Verify latitude/longitude displayed.
App shows latitude ≈ 40.7128, longitude ≈ ‑74.0060 with accuracy ≈ 5 m. No error toast. Location callback count ≥ 3.
LOC‑002Same as LOC‑001; additionally, network disabled (airplane mode on, Wi‑Fi off).1. Set mock GPS to (51.5074, -0.1278), accuracy 10 m.
2. Tap “Start Tracking”.
3. Wait 6 seconds.
4. Attempt reverse‑geocode lookup.
App displays coordinates correctly. Reverse‑geocode shows “Unable to resolve address” or cached value. No crash.
LOC‑003Device location mode = Battery saving; mock Wi‑Fi provider enabled; app at settings screen.1. Add two mock Wi‑Fi APs with known MACs and signal strengths (-60 dBm, -70 dBm).
2. Trigger location request via API.
3. Wait 5 seconds.
4. Read returned location.
Location returned approximates the trilaterated position of the two APs. Accuracy reported between 20‑50 m. No location‑service exception.
LOC‑004App in foreground; location permission set to Denied; mock GPS enabled.1. Attempt to start location updates via button.
2. Observe system dialog.
System shows permission rationale dialog. App does not receive location callbacks. No crash.
LOC‑005Location permission granted; mock GPS set to return null latitude/longitude.1. Tap “Start Tracking”.
2. Wait 10 seconds.
3. Check logs for error handling.
App receives onLocationChanged(null) or equivalent error callback. Displays “Location unavailable” toast. No ANR.
LOC‑006Device at API level 29 (Android 10); background location limit enabled; app requests foreground location only.1. Grant foreground location permission.
2. Start location updates.
3. Press home button to background the app.
4. Wait 30 seconds.
5. Check if location updates continue.
Location updates stop after ~a few seconds (per background limit). App receives onProviderDisabled‑style callback or no further onLocationChanged. No battery drain spike.
LOC‑007Device API level 33 (Android 13); precise location permission toggle off; approximate location allowed.1. Set location to approximate only.
2. Request ACCESS_FINE_LOCATION.
3. Attempt to start updates.
System prompts to upgrade to precise location. If user denies, app receives only coarse location (accuracy ≈ 500 m). No crash.
LOC‑008Mock GPS set to simulate movement at 120 km/h along a straight line; app displays speedometer.1. Set initial coordinate (0,0).
2. Start location updates.
3. Increment latitude by 0.001° every 0.5 seconds (approx 111 m/s).
4. Read speed value from UI every second.
Speed displayed approximates 111 m/s (≈ 400 km/h) within 5 % tolerance. No jitter spikes > 20 % due to timestamp handling.
LOC‑009Geofence registered with radius 50 m around (35.6895, 139.6917); device stationary at center.1. Add geofence via API.
2. Wait for dwell transition (default 30 seconds).
3. Simulate exit by moving mock GPS to (35.6905, 139.6927) (≈ 115 m away).
4. Wait 10 seconds.
App receives GEOFENCE_TRANSITION_EXIT event. No premature entry/exit events. Log shows correct timestamp.
LOC‑010Device in Doze mode (API ≥ 23); app requests location updates with priority PRIORITY_HIGH_ACCURACY.1. Enable Doze via adb shell dumpsys deviceidle force-idle.
2. Start location updates.
3. Wait 2 minutes.
4. Check if location callbacks still occur.
Location updates are throttled to ~≤ 1 per minute (per Doze behavior). App receives updates at expected low frequency. No crash.
LOC‑011Mock GPS accuracy set to 0 m (best‑case); app displays accuracy circle on map.1. Set mock GPS to any coordinate, accuracy 0 m.
2. Start tracking.
3. Observe map UI.
Accuracy circle radius renders as minimal (often 1‑2 px due to UI scaling). No division‑by‑zero errors.
LOC‑012Mock GPS accuracy set to maximum supported value (e.g., 2000 m); app shows accuracy indicator.1. Set mock GPS accuracy to 2000 m.
2. Start tracking.
3. Verify UI.
Accuracy indicator shows large circle; app does not treat value as invalid. No crash.
LOC‑013Simulated altitude change: mock GPS provides altitude from 0 m to 2000 m over 30 seconds.1. Start location updates.
2. Increment altitude by ~66 m each second.
3. Read altitude value from UI or log.
Altitude updates smoothly, reflecting the simulated change. No clamping at 0 m or 2000 m unless device limits apply.
LOC‑014Time‑zone shift: device time‑zone set to UTC‑5; app displays local time derived from location timestamp.1. Set device time‑zone to America/New_York (UTC‑5).
2. Set mock GPS timestamp to current UTC.
3. Start tracking.
4. Read displayed local time.
Displayed local time equals UTC‑5 conversion of the timestamp. No offset errors.
LOC‑015Network latency injection: reverse‑geocode API delayed 8 seconds (simulated via proxy).1. Enable mock GPS with valid fix.
2. Trigger reverse‑geocode lookup.
3. Introduce 8 s delay on the HTTP response.
4. Observe UI.
App shows loading spinner for ≤ 8 seconds, then displays address or timeout message. No UI freeze; main thread remains responsive.
LOC‑016Multiple location clients: app A requests high‑accuracy updates; app B requests passive updates.1. Install two test apps on same device.
2. Grant both location permissions.
3. Start high‑accuracy updates in App A.
4. Monitor passive callbacks in App B.
5. Verify App B receives updates without extra power drain.
App B receives location updates at same frequency as App A (passive). No additional GPS icon appears for App B. Battery impact ≤ 5 % increase vs. baseline.
LOC‑017Simulated GPS jump: mock provider returns a position 500 km away after 5 seconds of steady fixes.1. Provide steady fixes for 5 seconds.
2. Suddenly jump to distant coordinate.
3. Observe app’s handling (e.g., speed filter, distance‑threshold).
App discards the outlier if speed > threshold (e.g., > 200 m/s) or logs a “GPS jump” warning. Position on map does not teleport; either holds previous position or smooths via filter. No crash.
LOC‑018Battery‑saver mode enabled; app requests location with PRIORITY_LOW_POWER.1. Turn on Battery Saver.
2. Request low‑power location updates.
3. Wait 2 minutes.
4. Check update frequency.
Updates occur at low‑power interval (≥ ~ 1 per minute). GPS icon may appear briefly. App continues to function.
LOC‑019Simulated NFC‑triggered geofence: tapping an NFC tag writes a latitude/longitude; app reads and creates a geofence.1. Tap NFC tag with encoded coordinates (37.7749, -122.4194).
2. App reads tag and adds geofence radius 20 m.
3. Move mock GPS inside radius.
4. Wait for dwell transition.
App receives geofence entry event after dwell time. No delay > 5 seconds beyond expected.
LOC‑020Permission never‑asked state: app freshly installed, location permission not yet requested.1. Launch app.
2. Attempt to start location updates.
3. Observe system permission dialog.
System shows runtime permission rationale. App does not receive location data until user grants. No crash if denied.

*Feel free to extend this table with additional cases specific to your product (e.g., indoor‑positioning via BLE beacons, barometer‑based altitude, or carrier‑aggregation‑enhanced LTE positioning).*

5. Data Setup and Environment Preparation

Reliable location testing hinges on repeatable control over the inputs that the location subsystem consumes. Below are practical techniques you can apply in both manual and automated contexts.

5.1 Mocking GPS Providers

5.2 Using Emulators vs. Real Devices

AspectEmulator/SimulatorPhysical Device
Control granularityHigh – can inject exact latitude, altitude, speed, satellite countLimited – you can only spoof via mock location APIs; real RF behavior is opaque
PerformanceFast start‑up, no thermal throttlingReal‑world battery, temperature, sensor noise effects
OS‑specific quirksMay miss vendor‑specific location‑service bugsCaptures OEM modifications (e.g., Xiaomi’s location‑service power‑saving)
CostFree (part of SDK)Requires device lab or cloud‑based device farm

A robust strategy combines both: use emulators for repeatable functional checks and a rotating set of real devices for regression and performance validation.

5.3 Time‑Zone and Date Handling

Location timestamps are usually expressed in UTC milliseconds since epoch. Tests that depend on local‑time display must:

5.4 Network Condition Simulation

Reverse‑geocoding, place‑search, and map‑tile downloads rely on HTTP. To emulate adverse conditions:

6. Prioritization and Traceability to Requirements

A test matrix grows quickly; linking each case to a requirement and assigning a priority ensures that limited testing effort focuses on the highest‑impact areas.

6.1 Mapping Test Cases to Functional Requirements

Create a simple traceability table (requirement ID → test‑case IDs). Example:

Requirement IDDescriptionCovered By Test‑Case IDs
REQ‑LOC‑001App shall obtain a location fix within 10 s under good signal.LOC‑001, LOC‑002, LOC‑008
REQ‑LOC‑002App shall handle missing latitude/longitude gracefully.LOC‑005, LOC‑011, LOC‑012
REQ‑LOC‑003App shall trigger geofence entry/exit events with ≤ 5 s latency.LOC‑009, LOC‑019
REQ‑LOC‑010App shall respect background‑location limits on Android 10+.LOC‑006, LOC‑010
REQ‑LOC‑015App shall display accurate speed derived from location updates.LOC‑008, LOC‑017

Having this matrix lets you run a subset (e.g., all cases for REQ‑LOC‑003) when you change geofence logic.

6.2 Risk‑Based Prioritization

Assign a priority based on two factors: impact (user‑visible severity) and likelihood (chance of occurrence in the field). A simple 3×3 grid works:

Impact \ LikelihoodLowMediumHigh
High (crash, data loss)P2P1P0
Medium (incorrect UI, missing feature)P3P2P1
Low (cosmetic, rare edge)P4P3P2

Apply the grid to each test case:

Focus first on P0 and P1 cases; schedule P2‑P4 for each release cycle or nightly runs.

6.3 Coverage Metrics

Track the following quantitative signals to gauge test‑suite health:

7. Manual Execution vs. Autonomous Exploration with SUSA

Even the most exhaustive manual test suite can miss scenarios that only appear when real users interact with the app in unpredictable ways. Combining scripted cases with autonomous exploration yields complementary coverage.

7.1 Manual Test‑Case Execution Checklist

Before handing a test case to a human tester, verify:

  1. Device preparation – location mode, mock provider status, battery level, network condition.
  2. Prerequisite state – app logged in, any onboarding completed, permissions set as required.
  3. Step clarity – each action is unambiguous; include expected UI text or log messages.
  4. Oracles – define how the tester will verify success (visual check, logcat grep, API response).
  5. Cleanup – steps to reset mock location, disable airplane mode, close the app.

A tester can then follow the checklist, record pass/fail, and attach logs or screenshots.

7.2 How SUSA Augments Location‑Service Testing

SUSA (the autonomous QA platform) can explore an app without any pre‑written scripts, generating real user interactions such as taps, swipes, and system‑dialog handling. When pointed at an APK or a web URL, SUSA:

While SUSA does not replace deliberately crafted test cases for complex flows (like a multi‑step geofence‑setup wizard), it excels at finding surprise defects that only manifest under particular interaction patterns—such as a background service that fails to restart after the user force‑stops the app from the recent‑tasks list.

7.3 Combining Scripted Cases with Autonomous Sessions

A practical workflow:

  1. Run the manual/automated test matrix (Sections 4‑6) on every commit. This guarantees coverage of known requirements.
  2. Trigger a SUSA exploration nightly or before a release candidate. Configure it to:
  1. Triangulate results: If SUSA reports a crash on a screen not covered by your matrix, add a new test case (e.g., “Location permission denied while in the middle of a payment flow”) to the matrix and promote it to P1.
  2. Feedback loop: Use SUSA’s cross‑session learning to inform future manual test design—e.g., if it repeatedly finds that toggling airplane mode while a geofence is active triggers a toast, incorporate that scenario into your matrix.

This hybrid approach leverages the repeatability of scripted tests and the breadth of autonomous exploration, delivering higher confidence that location services behave correctly in the wild.

8. Automation Strategies: Appium, Playwright, and Custom Scripts

Turning the test matrix into executable checks requires automation frameworks that can control location mocking, assert on UI or API responses, and integrate with CI pipelines.

8.1 Sample Appium Script for Android GPS Mock


import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import java.net.URL;
import java.time.Duration;

public class GpsMockTest {
    public static void main(String[] args) throws Exception {
        UiAutomator2Options opts = new UiAutomator2Options()
                .setAppPackage("com.example.myapp")
                .setAppActivity(".MainActivity")
                .setAutomationName("UiAutomator2")
                .setNoReset(true);

        AndroidDriver driver = new AndroidDriver(new URL("http://localhost:4723/wd/hub"), opts);
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));

        // 1. Enable mock location via ADB (pre‑step, can be done in @Before)
        Runtime.getRuntime().exec("adb shell settings put secure mock_location 1");
        Runtime.getRuntime().exec("adb shell appops set com.example.myapp android:mock_location allow");

        // 2. Send a fixed geo coordinate
        driver.executeScript("mobile: geoLocation", 
                ImmutableMap.of("latitude", 37.7749, "longitude", -122.4194, "accuracy", 5));

        // 3. Start tracking in the app
        WebElement startBtn = driver.findElement(By.id("btn_start_tracking"));
        startBtn.click();

        // 4. Wait for location text to appear
        WebElement locText = driver.waitUntil(
                ExpectedConditions.visibilityOfElementLocated(By.id("tv_location")), 
                Duration.ofSeconds(8));

        String displayed = locText.getText();
        assert displayed.contains("37.7749") && displayed.contains("-122.4194")
                : "Location not displayed correctly: " + displayed;

        // 5. Simulate loss of fix
        driver.executeScript("mobile: geoLocation", 
                ImmutableMap.of("latitude", 0, "longitude", 0, "accuracy", 0, "available", false));
        Thread.sleep(12000); // wait for timeout handling

        // 6. Verify toast or UI indicator
        WebElement toast = driver.findElement(By.xpath("//android.widget.Toast[contains(@text,'unavailable')]"));
        assert toast.isDisplayed();

        driver.quit();
    }
}

Key points:

8.2 Sample Playwright Script for Web Geolocation


const { test, expect } = require('@playwright/test

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