How to Test Push Notifications on iOS (Complete Guide)
How to Test Push Notifications on iOS (Complete Guide) starts with understanding why push notifications are a critical part of the user experience and where they commonly fail. In this guide you will
How to Test Push Notifications on iOS (Complete Guide) starts with understanding why push notifications are a critical part of the user experience and where they commonly fail. In this guide you will find a detailed test matrix, step‑by‑step manual procedures, automated scripts using XCTest/XCUITest, environment setup tips, accessibility and security checks, and a look at how autonomous, persona‑driven exploration can surface issues that scripted tests miss. Each section contains concrete examples, commands, and tables you can copy straight into your workflow.
Why Push Notification Testing Matters in iOS
Push notifications are the primary channel for re‑engaging users, delivering time‑sensitive information, and driving conversions. A broken notification can lead to missed alerts, degraded trust, and even app store rejections if the payload violates Apple’s guidelines. Unlike UI elements that are visible on screen, notifications operate outside the app’s main thread, relying on the Apple Push Notification service (APNs), the device’s notification center, and the app’s handling code. Failures often appear only after a release because they depend on factors such as certificate validity, token refresh, background execution limits, and user‑granted permissions. Testing push notifications therefore requires a blend of backend validation, device‑side verification, and user‑interaction checks.
Common Failure Modes Seen in Production
Before diving into the test matrix, it helps to know the patterns that repeatedly cause production incidents:
| Failure Category | Typical Symptom | Root Cause |
|---|---|---|
| Token mismatch | Device never receives a push | APNs token changed after app reinstall or iOS update; backend still uses old token |
| Expired/invalid certificate | Silent failure on server side; no error logged | APNs certificate not renewed; using development cert for production build |
| Payload too large | Notification dropped silently | Payload exceeds 4 KB limit (including JSON overhead) |
| Silent push not delivered | Background fetch never triggered | content‑available flag set but app lacks Background Modes capability or user disabled background refresh |
| Notification center settings | User sees no alert despite push arriving | User disabled notifications for the app or set alert style to None |
| Localization bug | Wrong language in alert body | Payload uses hard‑coded strings instead of leveraging NSLocalizedString or user’s locale |
| Accessibility omission | VoiceOver does not read notification | Missing accessibilityLabel on custom notification content UI |
| Security leak | Sensitive data exposed in notification preview | Payload includes personal data and showsPreview set to YES without user consent |
Understanding these patterns informs the test cases that follow.
How to Test Push Notifications on iOS (Complete Guide): Test Matrix Overview
The matrix below organizes tests by dimension (happy path, error paths, edge cases, accessibility, security) and by verification point (backend, device, user interaction). Use it as a checklist when planning manual or automated suites.
| Test ID | Category | Description | Expected Result | Verification Method |
|---|---|---|---|---|
| P1 | Happy path | Send a standard alert notification with title, body, and sound | Notification appears in Notification Center, alert shows, sound plays | Manual observation or XCUITest expectation for UNNotification |
| P2 | Happy path | Send a silent push (content‑available: 1) with no alert | App wakes in background, performs fetch, no UI shown | Background task log, application(_:didReceiveRemoteNotification:fetchCompletionHandler:) |
| P3 | Error path | Use an expired APNs certificate | Server returns BadCertificate error; device receives nothing | Monitor APNs feedback server or console error |
| P4 | Error path | Send payload >4 KB | APNs rejects with PayloadTooLarge error | Check APNs response status code |
| P5 | Edge case | Token rotation after device restore | New token registered with backend; old token no longer works | Compare device token before/after restore; verify backend updates |
| P6 | Edge case | User denies notification permission at launch | No alert appears; didFailToRegisterForRemoteNotificationsWithError called | Prompt user to deny; observe callback |
| P7 | Accessibility | Send notification with custom UI content | VoiceOver reads title and body correctly | Run Accessibility Inspector or XCTest with UIAccessibility |
| P8 | Localization | Send notification with localized strings based on device language | Alert displays in correct language | Change device language; verify text |
| P9 | Security | Send payload containing PII (e.g., email) with showsPreview: false | Notification appears but preview hidden on lock screen | Lock device; check notification view |
| P10 | Stress | Send 100 notifications in quick succession | Device queues them; no crash or excessive battery drain | Monitor Console for jetsam events; observe battery usage |
| P11 | Interruption | Send notification while app is in foreground presenting a modal | Notification appears as banner (if alert style set) or in center depending on UNNotificationPresentationOptions | Verify presentation options handled in userNotificationCenter(_:willPresent:withCompletionHandler:) |
| P12 | Regression | After SDK update, re‑run happy path and silent push | No regression in delivery or handling | Automated CI job runs matrix on each commit |
This matrix can be expanded with additional rows for specific features like grouped notifications, critical alerts, or time‑sensitive notifications.
How to Test Push Notifications on iOS (Complete Guide): Manual Testing Steps
Manual testing remains valuable for exploratory checks, especially when validating user‑visible aspects such as alert style, sound, and accessibility. Follow this step‑by‑step procedure on a physical device or simulator:
- Prepare the device
- Ensure the device is running iOS 16 or later (older versions may lack certain UNNotificationCenter APIs).
- Enable Developer → Network Link Conditioner if you want to simulate poor connectivity.
- Verify that the app has notification permission (
Settings → Notifications →).
- Obtain a device token
- Run the app in debug mode.
- In
application(_:didRegisterForRemoteNotificationsWithDeviceToken:), print the token as a hex string. - Copy the token; you will need it to address APNs.
- Generate a test push via curl
curl -v -d '{
"aps": {
"alert": {
"title": "Test Title",
"body": "Test Body"
},
"sound": "default"
}
}' \
-H "apns-topic: com.example.myapp" \
-H "authorization: bearer <YOUR_JWT>" \
--http2 \
https://api.push.apple.com/3/device/<DEVICE_TOKEN>
- Replace
with a valid JWT signed using your APNs key (see the environment setup section). - Replace
with the hex token from step 2.
- Validate delivery
- Look for the alert in Notification Center or as a banner.
- Confirm that the sound plays (if not silenced).
- If using a custom notification UI, verify that the view loads correctly.
- Test silent push
- Modify the payload to include
"content-available": 1and remove thealertdictionary. - Add a log statement in
application(_:didReceiveRemoteNotification:fetchCompletionHandler:). - Observe the log when the push arrives; ensure the completion handler is called with
.newData.
- Check permission denial flow
- In Settings, turn off notifications for the app.
- Send a regular alert push.
- Verify that
application(_:didFailToRegisterForRemoteNotificationsWithError:)receives an error and that no UI appears.
- Accessibility verification
- Enable VoiceOver (
Settings → Accessibility → VoiceOver). - Send a notification with custom content.
- Swipe to hear the notification; ensure title and body are spoken correctly.
- Localization check
- Change device language to Spanish (
Settings → General → Language & Region → iPhone Language). - Send a push that uses localized strings.
- Confirm the alert appears in Spanish.
- Security/privacy test
- Send a push containing a sensitive field (e.g.,
"email": "user@example.com"). - Set
"mutable-content": 1and provide a notification service extension that modifiesshowsPreviewtofalse. - Lock the device and view the notification; ensure the email is hidden.
- Clean up
- Delete the device token from your backend test environment to avoid accidental production pushes.
- Reset notification permissions if you changed them for testing.
These steps can be scripted with tools like fastlane or custom shell scripts, but performing them manually at least once per release helps catch issues that automated checks might overlook (e.g., UI rendering glitches).
How to Test Push Notifications on iOS (Complete Guide): Automated Approaches with XCTest and XCUITest
Automated tests give you repeatable verification of the happy path and selected error conditions. While you cannot directly trigger APNs from within a test target, you can simulate the delivery by invoking the notification handling APIs directly or by using a local push server.
Setting up a local push simulator
A lightweight option is to use the NSPushNotifications framework available in Xcode’s simulator. It lets you send a notification to the simulated device via xcrun simctl push.
# Send a standard alert notification to the booted simulator
xcrun simctl push booted com.example.myapp <<JSON
{
"aps": {
"alert": {
"title": "Automated Test",
"body": "This is from XCUITest"
},
"sound": "default"
}
}
JSON
XCTest unit test for notification handling
You can unit test the delegate methods by injecting a mock UNUserNotificationCenter.
import XCTest
import UserNotifications
final class NotificationHandlerTests: XCTestCase {
var handler: NotificationHandler!
// your class that conforms to UNUserNotificationCenterDelegate
var mockCenter: MockUNUserNotificationCenter!
override func setUp() {
super.setUp()
mockCenter = MockUNUserNotificationCenter()
handler = NotificationHandler(center: mockCenter)
}
func testDidReceiveNotification_triggersAnalytics() {
// Arrange
let notification = UNNotification(
request: UNNotificationRequest(
identifier: "test",
content: {
let content = UNMutableNotificationContent()
content.title = "Test"
content.body = "Body"
return content
}(),
trigger: nil)
)
// Act
handler.userNotificationCenter(
mockCenter,
didReceive: notification.request.content,
withCompletionHandler: {}
)
// Assert
XCTAssertTrue(mockCenter.didReceiveCalled)
XCTAssertEqual(mockCenter.lastReceivedContent?.title, "Test")
}
}
MockUNUserNotificationCenter is a simple stub that records calls.
XCUITest for UI interaction
When the app is in the foreground, you can assert that a notification appears as a banner or alert.
func testNotificationAppearsAsBanner() {
let app = XCUIApplication()
app.launch()
// Use simctl to push a notification while the app is running
let pushScript = """
xcrun simctl push booted com.example.myapp <<JSON
{
"aps": {
"alert": {
"title": "UI Test",
"body": "Banner"
}
}
}
JSON
"""
let task = Process()
task.launchPath = "/bin/bash"
task.arguments = ["-c", pushScript]
task.launch()
task.waitUntilExit()
// Expect a banner to appear for a short time
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let banner = springboard.otherElements["NotificationShortLookView"]
XCTAssertTrue(banner.waitForExistence(timeout: 2), "Notification banner did not appear")
}
Note: The test must run on a real device or simulator where you have permission to execute simctl. In CI, you can use a macOS runner with Xcode command‑line tools.
Testing silent pushes with background fetch
You can assert that a background fetch occurs by checking a flag set in the handler.
func testSilentPushTriggersFetch() {
let handler = NotificationHandler()
let notification = UNNotification(
request: UNNotificationRequest(
identifier: "silent",
content: {
let c = UNMutableNotificationContent()
c.setValue(1, forKeyPath: "aps.content-available")
return c
}(),
trigger: nil)
)
handler.userNotificationCenter(
UNUserNotificationCenter.current(),
didReceive: notification.request.content,
withCompletionHandler: { _ in }
)
XCTAssertTrue(handler.backgroundFetchPerformed)
}
Automated tests give you confidence that the core logic works, but they do not replace manual checks for user‑visible aspects such as sound, vibration, or lock‑screen preview.
Setting Up the Test Environment (Certificates, Tokens, Sandbox)
A reliable push‑notification test pipeline starts with correct credentials and a sandbox that mirrors production as closely as possible.
Creating an APNs authentication key
- In the Apple Developer portal, navigate to Certificates, Identifiers & Profiles → Keys.
- Click + to create a new key, enable Apple Push Notification service (APNs), and download the
.p8file. - Note the Key ID and your Team ID.
Generating a JWT for APNs
Use a library or the following Swift snippet to create a token valid for 20 minutes (the maximum allowed).
import Foundation
import CryptoKit
func generateAPNsJWT(keyID: String, teamID: String, privateKeyData: Data) throws -> String {
let header = ["alg": "ES256", "kid": keyID]
let now = Date()
let payload: [String: Any] = [
"iss": teamID,
"iat": Int(now.timeIntervalSince1970),
// APNs rejects tokens with future exp > 20 minutes
"exp": Int(now.addingTimeInterval(1200).timeIntervalSince1970)
]
func jsonBase64Encode(_ obj: Any) throws -> String {
let data = try JSONSerialization.data(withJSONObject: obj, options: [])
return data.base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
}
let encodedHeader = try jsonBase64Encode(header)
let encodedPayload = try jsonBase64Encode(payload)
let signingInput = "\(encodedHeader).\(encodedPayload)"
// Sign with ECDSA using P‑256
let p256 = try Curve25519.Signing.PrivateKey(rawRepresentation: privateKeyData)
let signature = try p256.signature(for: Data(signingInput.utf8))
let sigBase64 = signature.rawRepresentation.base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
return "\(signingInput).\(sigBase64)"
}
Replace the Curve25519 reference with the appropriate P‑256 implementation if you use a different crypto library.
Using the token with curl
The JWT generated above serves as the bearer token in the authorization header of the APNs request (see the manual testing section). Keep the token short‑lived and regenerate it for each test batch to avoid expiration issues.
Sandbox vs Production
- Sandbox: Use
api.sandbox.push.apple.comand a sandbox certificate or key. Device tokens obtained in the sandbox environment are different from production tokens. - Production: Use
api.push.apple.com. Never mix sandbox tokens with production endpoints; APNs will reject them withBadDeviceToken.
Managing device tokens in tests
Store tokens in a secure vault (e.g., AWS Secrets Manager, HashiCorp Vault) and inject them into your test scripts at runtime. Rotate tokens periodically and invalidate old ones by calling UNUserNotificationCenter.current().removeAllDeliveredNotifications() and UNUserNotificationCenter.current().removeAllPendingNotificationRequests() between test runs.
Simulator considerations
The simulator does not require a real APNs connection for local pushes via simctl push. However, to test token registration you must still run the app and capture the token from didRegisterForRemoteNotificationsWithDeviceToken. The simulator will generate a fake token that works with simctl.
By establishing a repeatable credential flow, you eliminate a common source of flaky push‑notification tests.
How to Test Push Notifications on iOS (Complete Guide): Leveraging Autonomous, Persona‑Driven Exploration
Scripted tests excel at verifying known paths, but they often miss edge cases that arise from real‑world user behavior. Autonomous QA platforms such as SUSATest explore an app without pre‑written scripts, simulating a variety of user personas (curious, impatient, novice, accessibility‑focused, power user, etc.) and exercising the app’s UI in ways that reveal hidden bugs.
How autonomous exploration finds push‑notification bugs
- Person‑specific interaction patterns
- An *impatient* persona may tap a notification immediately after it arrives, triggering the app’s foreground handling code while a background fetch is still in progress. This can expose race conditions between
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)anduserNotificationCenter(_:didReceive:withCompletionHandler:). - A *novice* persona might ignore the notification for several minutes, letting the system coalesce multiple alerts. This tests the app’s handling of grouped notifications and whether it correctly de‑duplicates actions.
- Exploration of system settings
The autonomous agent periodically visits the Settings → Notifications pane for the app under test, toggles authorization, changes alert styles, and disables sounds. Each change triggers a new registration cycle, revealing issues such as failure to re‑register for remote notifications after a denial‑then‑allow cycle.
- Simulation of adverse conditions
- Network latency is injected via the built‑in link conditioner, causing APNs requests to time out. The agent checks whether the app gracefully handles missing notifications and retries token registration when connectivity returns.
- Battery‑low mode is enabled to verify that the app respects the system’s push‑ throttling guidelines and does not attempt to spawn excessive background tasks.
- Detection of silent‑push misuse
By monitoring console logs for calls to application(_:didReceiveRemoteNotification:fetchCompletionHandler:) without a corresponding user‑visible alert, the agent can flag developers who inadvertently send silent pushes that perform heavy work, potentially violating App Store Review Guideline 2.5.2 (performance).
- Accessibility and localization checks
The agent switches VoiceOver on and off, changes the device language, and verifies that notification content is readable and correctly localized. Missing accessibilityLabel on custom notification UI or hard‑coded strings are reported as issues.
Integrating SUSA into your CI pipeline
You can run a short autonomous exploration as a post‑build step:
# Install the SUSA agent (if not already present)
pip install susatest-agent
# Run a 5‑minute exploratory session on the built .app or .ipa
susatest explore \
--device-id <UDID> \
--app-path ./MyApp.app \
--personas curious impatient novice accessibility \
--duration 300 \
--output ./susa-report.json
The resulting JSON report includes a list of discovered issues, each with severity, steps to reproduce, and associated logs. You can fail the build if any high‑severity push‑notification defect is found.
Benefits over pure scripted testing
- Coverage of unexpected user flows – The agent may discover that tapping a notification while a modal is presented leads to an inconsistent UI state, something a script that only tests the happy path would never see.
- Continuous learning – Each run updates the agent’s internal model of the app’s screens and dead ends, making subsequent explorations more efficient and able to reach deeper states.
- Persona‑specific insights – Reports often highlight which user segment is most affected by a bug, helping prioritize fixes (e.g., an accessibility issue that only impacts VoiceOver users).
While autonomous testing does not replace unit or UI tests, it complements them by surfacing problems that arise from real‑world variability. Incorporating a brief SUSA session into your nightly pipeline can dramatically reduce the chance of push‑notification regressions reaching production.
Accessibility and Localization Considerations for Push Notifications
Notifications are a prime accessibility touchpoint because they convey time‑sensitive information to users who may rely on assistive technologies. Likewise, localization ensures that users receive messages in their preferred language, which is critical for global apps.
Accessibility testing checklist
| Check | How to verify | Tools |
|---|---|---|
| VoiceOver reads title and body | Enable VoiceOver, swipe to hear the notification | Accessibility Inspector, manual inspection |
| Custom notification UI provides accessibilityLabel | Inspect the view hierarchy in Xcode’s debug navigator | Xcode UI testing with XCUIElement’s label property |
| Dynamic type respects user font size | Change Settings → Accessibility → Larger Text, send a notification, verify text scales | UI test with UIContentSizeCategory |
| Reduce motion respected | Enable Reduce Motion, ensure no animated effects in notification UI | Manual observation |
| Haptic feedback optional | Ensure that any custom haptics can be disabled via Settings → Accessibility → Touch → Vibration | Manual test |
Example XCTest for VoiceOver label:
func testNotificationAccessibilityLabel() {
let center = UNUserNotificationCenter.current()
let expectation = expectation(description: "Delegate called")
center.delegate = self
// Trigger a local notification for testing
let content = UNMutableNotificationContent()
content.title = "Test"
content.body = "Body"
content.userInfo = ["test": true]
let request = UNNotificationRequest(identifier: "test", content: content, trigger: nil)
center.add(request) { _ in
// In delegate method, capture the content and check its accessibility
expectation.fulfill()
}
waitForExpectations(timeout: 2, handler: nil)
}
In the delegate method, you can assert that content.title and content.body are non‑empty and that any custom view you provide sets accessibilityLabel.
Localization testing checklist
| Check | How to verify |
|---|---|
Notification uses NSLocalizedString or String(localized:) | Search codebase for hard‑coded strings in notification payloads |
| Correct language appears after switching device language | Change Settings → General → Language & Region, send a push, verify text |
| Right‑to‑left (RTL) layout respected | Set language to Arabic or Hebrew, ensure alignment mirrors |
| Date/time formats localized | If payload includes timestamps, confirm they appear in the user’s locale format |
| No truncated strings in limited space | Send long strings, verify they are not clipped in the banner or alert view |
A practical approach is to embed a localization verification step in your automated UI test:
func testNotificationLocalizationSpanish() {
// Set device language to Spanish via simctl (requires Xcode 15+)
let _ = try? Process.runCommand(
launchPath: "xcrun",
arguments: ["simctl", "spawn", "booted", "defaults", "write", "-g", "AppleLanguages", "(es)"])
// Restart SpringBoard to apply changes
_ = try? Process.runCommand(
launchPath: "xcrun",
arguments: ["simctl", "spawn", "booted", "killall", "-HUP", "SpringBoard"])
// Trigger a notification that uses a localized string
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let notification = springboard.otherElements["Notification"]
XCTAssertTrue(notification.waitForExistence(timeout: 5, "Notification not shown")
let label = notification.staticElements["HelloWorldKey".localized] // assume you have an extension
XCTAssertTrue(label.exists, "Localized string not found")
}
By treating accessibility and localization as first‑class concerns in your notification tests, you avoid releasing messages that are illegible, misaligned, or confusing to a sizable portion of your audience.
Security and Privacy Checks for Push Payloads
Push notifications can inadvertently leak personal data, violate user expectations, or be abused for tracking. A disciplined security review of the payload and its handling mitigates these risks.
Payload sanitization rules
- Never include sensitive personal data (email, phone number, health info) in the visible alert or sound fields. If such data is required for background processing, transmit it exclusively via the encrypted APNs channel and keep it out of the user‑visible
alertdictionary. - Limit payload size to under 4 KB; oversized payloads are rejected and can cause the device to drop the connection, leading to token invalidation.
- Use the
mutable-contentflag only when necessary. A notification service extension that modifies the content must be signed with the same provisioning profile as the main app and must not introduce additional network calls that could expose data. - Respect the
content-availableandsoundkeys. Silent pushes should perform only quick, lightweight tasks (e.g., updating a badge). Expensive work should be deferred to a background fetch scheduled viaBGTaskScheduler. - Honor user‑selected preview settings. If the user has disabled notification previews (Settings → Notifications → Show Previews → When Unlocked or Never), the system will hide the
alertdictionary. Do not attempt to circumvent this by placing critical info in thetitleorbodyfields; instead, rely on the app’s internal state to convey the information after the user opens the app.
Testing for data leakage
- Network inspection: Use a proxy such as Charles or mitmproxy to decrypt TLS traffic (install the proxy’s certificate on the device) and verify that no personal data appears in the APNs request body beyond the device token and payload.
- Console monitoring: Look for logs that inadvertently print the payload (e.g.,
print("Received push: \(userInfo)")). Replace such statements with a sanitized version that omits PII. - Unit test for extension: If you use a notification service extension, write a test that feeds a sample payload containing a fake email address and asserts that the extension’s
didReceive(_:withContentHandler:)does not include that email in the modifiedcontent’salertdictionary.
Example test for a service extension:
func testExtensionDoesNotLeakEmailInAlert() {
let input = UNNotificationContent()
input.userInfo = ["email": "user@example.com", "aps": ["alert": ["title": "Hi", "body": "Hello"]]]
let ext = NotificationService()
let expectation = expectation(description: "Content handler called")
ext.didReceive(
.init(request: .init(identifier: "test", content: input, trigger: nil),
bestAttemptContent: input.mutableCopy() as! UNMutableNotificationContent)
) { newContent in
XCTAssertFalse(newContent.userInfo.keys.contains("email"))
XCTAssertNil(newContent.alert?.body.range(of: "@"))
expectation.fulfill()
}
waitForExpectations(timeout: 1, handler: nil)
}
Validating APNs authentication security
- Key rotation: Schedule a quarterly rotation of your APNs auth key. Update your CI/CD pipeline to fetch the newest key from a secrets manager before each test run.
- Replay attack mitigation: APNs includes a timestamp in the JWT; ensure your server rejects tokens with an
iatolder than a few minutes to prevent replay. - TLS version: Confirm that your push provider uses TLS 1.2 or higher; older versions are deprecated by Apple.
By integrating these security checks into your test matrix, you reduce the risk of App Store rejection, user complaints, or regulatory issues stemming from insecure push notifications.
Tool Comparison: Manual vs Automated vs Autonomous Approaches
Choosing the right mix of techniques depends on your team’s velocity, the criticality of the notification flow, and the resources available for test maintenance.
| Approach | Strengths | Weaknesses | Typical Use‑Case | Example Tools |
|---|---|---|---|---|
| Manual exploratory | Immediate feedback on UI, sound, vibration; catches subtle rendering issues | Time‑consuming, not repeatable, hard to scale | Ad‑hoc validation before release, accessibility spot‑checks | Physical device, Xcode console, simctl push |
| Automated unit/UI | Repeatable, fast, integrates with CI, verifies delegate logic and background handling | Cannot directly trigger APNs; limited to simulated delivery; misses user‑perceived nuances | Regression testing of notification handling code, CI gate | XCTest, XCUITest, Fastlane, simctl push |
| Autonomous persona‑driven | Explores unscripted user behaviors, simulates real‑world conditions (network, battery, settings), surfaces edge cases missed by scripts | Requires third‑party tool or custom harness; results may need triage | Continuous discovery, pre‑release risk assessment, compliance checking | SUSATest, Firebase Test Lab (with custom scripts), custom UI‑explorer bots |
A balanced strategy might look like this:
- Unit tests for all delegate methods and background‑fetch logic (run on every commit).
- XCUITest scenarios that use
simctl pushto verify UI presentation and interaction (run nightly). - Manual exploratory session once per sprint focusing on accessibility, localization, and sound/vibration.
- Autonomous exploration (e.g., SUSA) scheduled weekly or before major releases to catch regressions that only appear under specific persona patterns or adverse conditions.
Checklist and Takeaways
Use this concise checklist before marking a push‑notification feature as ready for production.
Pre‑release checklist
- [ ] APNs authentication key is valid and not expired (check
expin JWT). - [ ] Device token is correctly registered
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