Next-Gen App & Browser Testing Cloud
Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

A practitioner guide to testing push notifications on real Android and iOS devices - APNs, Firebase Cloud Messaging, Appium automation, and the states that only real hardware reveals.

Vaishali Vatsayan
Author

Akshay Verma
Reviewer
Last Updated on: July 3, 2026
Overview
How do you test push notifications on real devices?
Trigger the notification through the real delivery service - Firebase Cloud Messaging (FCM) for Android, Apple Push Notification service (APNs) for iOS - then assert on physical hardware that it arrives, renders, and behaves correctly when tapped across foreground, background, and terminated app states.
Can you test push notifications on a simulator or emulator?
Only partially. A simulator can display a simulated payload, but it cannot validate real device-token registration, background or killed-state delivery, OEM battery optimization, or the runtime permission prompt. Those failures surface only on real devices.
What do you need to run these tests at scale?
Android runs 69.14% of the world's mobile devices and iOS runs 30.79%, according to StatCounter's June 2026 mobile OS data. Your push notification has to land on both, and each platform delivers it through a completely different pipeline.
The short version: to test push notifications on real Android and iOS devices, you trigger the notification through the real delivery service - FCM for Android, APNs for iOS - and assert its behavior on physical hardware. Simulators and emulators cannot reproduce real device tokens, terminated-state delivery, or OEM battery rules, so a push that looks fine on your laptop can still vanish on a user's phone. This guide walks through the iOS path, the Android and Firebase path, Appium automation, and the notification states that only real devices reveal. If you are new to the space, the mobile app testing learning hub covers the fundamentals this guide builds on.
A push notification is not a message your app draws on screen. It is an over-the-air payload that travels from your backend, through Apple's or Google's delivery service, to a specific device token, and is then rendered by the operating system - often while your app is not even running. Every link in that chain is a real-device concern.
Real hardware is where the parts an emulator glosses over actually execute. These are the failure points that only surface on a physical device:
This is the same reason hardware-dependent features like fingerprint and Face ID need physical devices. If you automate those flows too, the walkthrough on biometric authentication with Appium uses the same real-device approach.
Yes, but only for the parts that do not touch the real delivery network. Since Xcode 11.4, Apple's iOS Simulator can display a simulated remote notification: you drag an APNs payload file onto the Simulator window or run xcrun simctl push from the terminal. That is genuinely useful for checking how a payload parses and how the banner looks. It is not a real send - it never reaches APNs and uses no device token.
Android emulators with Google Play services can receive real FCM messages, which is closer to production. But they still run stock Android without the OEM battery layers, and Doze and background limits behave differently than on a shipped Samsung or Xiaomi handset. Here is what each environment can and cannot validate:
| What you are validating | Simulator / Emulator | Real Device |
|---|---|---|
| Payload parsing and banner layout | Yes (simulated payload on iOS; real FCM on Android emulator) | Yes |
| Real APNs / FCM delivery with a device token | iOS Simulator: no. Android emulator: partial | Yes |
| Background and terminated-state delivery | Unreliable | Yes |
| OEM battery optimization behavior | No | Yes |
| Runtime permission prompt (grant / deny / re-enable) | Partial | Yes |
| Delivery under real network profiles | No | Yes |
Use the simulator for a fast inner-loop check while you build the payload. Move to a real device before you trust the result - especially for anything a user experiences when the app is closed.
On iOS, every remote notification is delivered by Apple Push Notification service (APNs). There is no way around it - your backend or provider hands the payload to APNs, and APNs delivers it to a device token. Testing the real path on a physical iPhone follows five steps:
Registration, token handling, and payload structure are documented in Apple's Registering your app with APNs reference. If your iOS app uses Firebase, FCM forwards to APNs behind the scenes, so you still upload an APNs authentication key to Firebase and the real delivery is an APNs delivery. The permission prompt is where many iOS push flows quietly fail: test the granted path, the denied path, and the path where a user re-enables notifications from iOS Settings.
On Android, Firebase Cloud Messaging (FCM) is the delivery service. The flow mirrors iOS but the tooling is Firebase. To test it on a real Android device:
A minimal FCM HTTP v1 send looks like this - useful for scripting notifications into a test run rather than clicking through the console each time:
curl -X POST \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send \
-d '{
"message": {
"token": "DEVICE_FCM_TOKEN",
"notification": {
"title": "Order shipped",
"body": "Your order #1234 is on the way"
}
}
}'The token, payload keys, and delivery options are covered in the Firebase Cloud Messaging documentation. Remember the Android 13 permission gate: on newer devices the notification will not appear at all unless the user has granted the runtime notification permission, so make granting it part of your setup and test the denied path separately.
Appium does not send the push - it verifies the result. A common mistake is reaching for Appium's mobile: pushNotification command, but per the Appium XCUITest driver reference, that command only simulates a notification on the iOS Simulator through simctl and does not work on real iOS devices. The reliable pattern on real hardware is: trigger the notification through FCM or APNs, then use Appium to open the tray, assert the content, tap it, and validate the destination screen.
The critical capability is isRealMobile. With Appium desired capabilities, TestMu AI defaults to emulator and simulator execution - real device execution requires explicitly setting isRealMobile to true. Point the driver at the TestMu AI mobile hub and open the notification shade with driver.openNotifications():
// Real Android device on the TestMu AI cloud grid
UiAutomator2Options options = new UiAutomator2Options();
options.setPlatformName("android");
options.setDeviceName("Galaxy S24");
options.setPlatformVersion("14");
options.setApp("lt://APP_ID"); // your uploaded .apk / .aab build
options.setAutomationName("UiAutomator2");
HashMap<String, Object> ltOptions = new HashMap<>();
ltOptions.put("w3c", true);
ltOptions.put("isRealMobile", true); // route to a REAL device, not an emulator
ltOptions.put("build", "Push Notification Tests");
ltOptions.put("name", "FCM delivery - background state");
ltOptions.put("network", true); // capture network logs
ltOptions.put("devicelog", true); // capture device logs
options.setCapability("LT:Options", ltOptions);
String hub = "https://" + LT_USERNAME + ":" + LT_ACCESS_KEY
+ "@mobile-hub.lambdatest.com/wd/hub";
AndroidDriver driver = new AndroidDriver(new URL(hub), options);
// 1) Trigger the push from your backend / FCM while the app is backgrounded.
// 2) Open the notification shade and assert the notification arrived.
driver.openNotifications();
WebElement push = new WebDriverWait(driver, Duration.ofSeconds(20))
.until(ExpectedConditions.visibilityOfElementLocated(
By.xpath("//*[contains(@text,'Your order #1234 is on the way')]")));
// 3) Tap the notification and assert it deep-links into the app.
push.click();
Assert.assertTrue(driver.findElement(By.id("com.myapp:id/order_detail")).isDisplayed());On iOS, swap in XCUITestOptions and keep isRealMobile true; because mobile: pushNotification is off the table on real hardware, you trigger via APNs and assert the banner and tap-through the same way. For the desired-capabilities details, see the guide to Appium capabilities, and for asserting the system dialogs that appear alongside notifications, the walkthrough on handling alerts and popups in Appium. New to the framework? Start with the Appium tutorial to run your first cloud session.
Note: Run your Appium push notification suite across 10,000+ real Android and iOS devices on TestMu AI, with network profiles and full device logs to debug delivery. Start testing free.
A single "did the notification arrive?" check misses most real bugs. Push behavior changes with the app's state, so validate each one independently:
| App state | What to assert |
|---|---|
| Foreground (app open) | The app receives and presents the notification correctly; in-app handling (badge, banner, or custom UI) fires as designed. |
| Background (app suspended) | The OS displays the banner; tapping it resumes the app on the correct screen with the right data. |
| Terminated (app killed) | The notification still arrives; tapping cold-starts the app and routes to the intended destination, not the default home screen. |
Beyond states, cover the behaviors users actually hit:
Foreground, background, and terminated delivery are defined at the OS level by Apple's UserNotifications framework and Android's notification system, which is exactly why they must be observed on real devices rather than inferred.
One real iPhone and one real Android phone on a desk cover two configurations. Production is thousands. A real device cloud closes that gap: TestMu AI provides on-demand access to 10,000+ real Android and iOS devices, so the same push test runs across OS versions and OEM skins without a physical device lab.
For push notification testing specifically, four capabilities matter:
Because pre-release builds often are not published to the app stores yet, a secure tunnel lets a cloud device reach a build hosted on your own network, so you can validate push flows on a staging build before it ships.
Start small: capture a real device token from a debug build, send one notification through FCM or APNs, and assert it on a real phone across foreground, background, and terminated states. Once that loop is solid, wrap it in Appium with isRealMobile set to true and add the permission, deep-link, and poor-network cases.
From there, scale the matrix on TestMu AI's real device cloud so the same suite runs across the Android and iOS versions your users actually carry. The getting started with Appium testing docs walk through connecting your first real-device session, and a push that has been validated on real hardware is one you can ship with confidence.
Author
Vaishali Vatsayan is a Community Contributor at TestMu AI with 5+ years of experience in copywriting, content strategy, and UX writing for SaaS and AI products. She is skilled in test automation and mobile automation testing across Android and iOS, and specializes in product copy, onboarding flows, microcopy, UI strings, and brand voice. She worked as a Senior Copywriter at Leena AI.
Reviewer
Akshay Verma is a Senior Product Manager at TestMu AI (formerly LambdaTest), where he drives adoption and product-led growth across the testing platform, focusing on onboarding, time-to-value, and unlocking new markets. Earlier in the company he drove the execution of product features that contributed to a 2x revenue-growth trajectory within a year. Before TestMu AI he helped build the Revenue Intelligence product from scratch at Next Quarter, which went on to drive 43% of that company's revenue. Akshay holds a B.Tech in Computer Science from Delhi Technological University.
Did you find this page helpful?
More Related Blogs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance