Testing push notifications in a development build is more than sending a message to a phone and checking whether it appears. A useful test proves that the complete path works: the app registers correctly, the notification service accepts the request, the operating system permits delivery, the device receives the payload, and the app handles it as intended.
Development testing should also protect production users. The safest approach is to separate development identities, credentials, targets, and test data from production wherever the platform allows it. Then create repeatable tests that cover both successful delivery and the failure cases your product must handle.
Define what a successful test means
Before sending a notification, decide which part of the system you are testing. Push delivery has several distinct stages:
- The app requests notification permission where required.
- The client registers the device and obtains a provider token.
- The client sends or synchronises that registration with your backend or notification service.
- Your server accepts a request with the expected authentication and notification fields.
- The push provider accepts the message for the target.
- The operating system delivers, suppresses, or transforms the notification.
- The app responds correctly when the user taps the notification or when a data payload is received.
A test that only checks the visible banner can miss errors in registration, targeting, deep links, analytics, or background handling. Write down the expected result for each stage. For example, a test may require the device to be registered, the server request to be accepted once, the notification to appear while the app is closed, and a particular screen to open after a tap.
Keep development and production separate
Use a clearly identifiable development application and development data. Do not rely on the notification title alone to distinguish environments, because a test message can still reach the wrong audience if its target is misconfigured.
Useful separation measures include:
- Use different application identifiers or build configurations where your mobile platform requires them.
- Store development API keys separately from production secrets.
- Maintain separate test users, tags, segments, and device registrations.
- Make the selected environment visible in application logs and internal diagnostics.
- Prevent development builds from loading production target lists by default.
- Add safeguards to server-side test tools, such as requiring an explicit development target.
A development build should never silently fall back to production configuration. Fail clearly when an expected development value is missing. This is safer than allowing a default value to decide where a notification goes.
Remember that operating-system permissions and provider tokens can be environment-specific. A token generated by one app configuration may not be valid for another. If a device appears to be registered but does not receive messages, confirm that the token, application environment, and credentials all belong together.
Verify client registration first
Start with registration before testing message content. Install the development build on a real device, launch it, and complete the permission flow. Confirm that the client SDK reports the expected registration and token lifecycle events through your application diagnostics.
Check the following:
- The app requests permission at an appropriate point in the user journey.
- The user grants permission, or the app records that permission was denied.
- A provider token is received and stored safely.
- The token is associated with the intended user or anonymous installation.
- Registration is retried if the network is temporarily unavailable.
- Token changes update the server-side record rather than creating stale duplicates.
- Signing out removes or changes the user association according to your design.
Test a fresh install, an upgrade, a reinstall, and a permission change. On a real device, disable and re-enable notifications in system settings, then check whether the app detects the new state. Also test token rotation rather than assuming a token remains permanent.
Avoid logging complete tokens in shared logs. A masked token, a stable internal device identifier, and timestamps are usually enough to correlate a test without exposing unnecessary data.
Test a server-side send with a narrow target
Once registration is confirmed, send to one known development target. HoneyNotify server-side sends use POST /v1/notifications with a Bearer API key and an Idempotency-Key. A notification requires a title, body, and target. Targets can address a device, user, tag, segment, or all enabled devices.
For the first test, choose the narrowest target available, normally one development device or user. Avoid testing with all enabled devices until target selection and environment isolation have been verified.
Confirm that your request handling covers both accepted and rejected requests:
- The API key is loaded from a secret store rather than committed to source control.
- The request includes the required title, body, and target fields.
- The Idempotency-Key is stable when retrying the same intended send.
- A new key is used for a genuinely new notification.
- The server records the request outcome and any provider response it receives.
- Retries do not accidentally create duplicate notifications.
Idempotency is especially important when a network timeout occurs after the service may already have accepted the request. Treating every timeout as permission to send again can produce duplicates. Use the idempotency mechanism consistently and make its scope clear in your server implementation.
Test foreground, background, and terminated states
Notification behaviour can differ depending on the app's state. Test at least these scenarios:
- The app is open in the foreground.
- The app is running in the background.
- The app has been closed by the user.
- The device is locked.
- The device is offline when the send occurs and reconnects later.
Record what should happen in each case. A foreground message may be handled inside the app rather than displayed as a system notification, depending on the client implementation and operating-system rules. A background message may be displayed, passed to a handler, or affected by system restrictions.
Test the user action as well as delivery. Tapping a notification should open the intended screen, preserve relevant context, and behave safely if the referenced object has been deleted or the user is no longer signed in. If your payload contains custom data, validate missing, malformed, and unexpected values instead of assuming every notification was produced by the latest app version.
Check the payload and presentation
Use simple, recognisable content for the first delivery test. Include a unique test identifier in the body or in diagnostic data so that you can distinguish a new message from an old one. Do not put secrets, personal data, or internal credentials in notification payloads.
Then test realistic payload variations:
- Short and long titles.
- Short and long bodies.
- Non-ASCII characters and punctuation.
- Optional custom data.
- Deep-link or routing data.
- Missing optional values.
- Repeated sends with the same logical event.
Check how content is rendered on different screen sizes and system settings. Consider truncation, line breaks, badges, sounds, grouping, and user-level notification preferences. These behaviours should be verified on each supported platform rather than inferred from one device.
Build a small test matrix
A test matrix prevents a single successful device from creating false confidence. Include combinations that reflect your support policy:
- Each supported platform: iOS, Android, and Web Push where applicable.
- Development application configuration and supported release-like configuration.
- Fresh install and upgraded installation.
- Permission granted, denied, and later changed.
- Foreground, background, terminated, locked, and offline states.
- Direct device or user targeting, followed by tag or segment targeting.
- Current and rotated provider tokens.
- Signed-in and signed-out user states.
You do not need to run every combination manually for every change. Identify a small smoke suite for each build and a broader regression suite before release. Keep the expected result and evidence for each test, such as request logs, registration state, device timestamps, and screenshots where useful.
Diagnose failures systematically
When a notification does not appear, avoid immediately changing the message or sending repeatedly. Work through the delivery chain in order:
- Is the development build using the intended environment?
- Did the app receive permission and register successfully?
- Is the token current and associated with the expected device or user?
- Did the server send to the intended target?
- Was the request authenticated and accepted?
- Was the Idempotency-Key reused correctly during retries?
- Did the operating system suppress or delay presentation?
- Did the app receive the payload but fail while handling it?
- Is the device connected and able to receive push traffic?
Compare timestamps across the client, server, and device. Check whether the app has been force-stopped, whether system notification settings have changed, and whether battery or network restrictions apply. A notification that was accepted by the server is not necessarily proof that it was displayed to the user.
If you have imported OneSignal subscription IDs, those IDs can remain as device IDs when matching provider tokens later register. However, token rotation or a different provider environment can prevent matching. Treat an unmatched imported ID as a registration and environment investigation, not as evidence that the send request is faulty.
Common mistakes to avoid
- Testing only on an emulator when real-device behaviour is required.
- Using a production API key or production segment in a development build.
- Assuming a successful API response proves visible delivery.
- Treating provider tokens as permanent identifiers.
- Sending to all enabled devices before testing a single target.
- Repeating timed-out requests without an idempotency strategy.
- Testing only while the app is open.
- Ignoring denied permissions and system-level notification settings.
- Putting sensitive data in notification titles, bodies, or custom payloads.
- Failing to test notification taps and invalid deep-link data.
- Logging credentials or complete device tokens.
Conclusion
A reliable development test follows the notification from registration through server acceptance, provider delivery, operating-system handling, and application behaviour. Separate environments, use a narrow target, verify tokens and permissions, send with an idempotency key, and test several app states. A small repeatable test matrix will reveal more than repeated manual sends, while clear logs make failures easier to isolate before they reach production.
