Testing push notifications on iOS and Android

October 01, 2014

Push notifications – mobile application developers and testers love & hate them in the very same time. While giving unique opportunities, they might be hard to test, as it requires integration of multiple components, including third-party services – APNS (Apple Push Notification Services) and GCM (Google Cloud Messaging). At CodingFingers we’ve established some best practices that helps us to build push-enabled apps & test them properly. We hope they will help you, no matter if you are building app for startup or enterprise company


  • Add proper logging! You won’t be able to debug production app, so proper logigng will help you a lot. Remember to add log statemens in GcmIntentService.onHandleIntent(), GcmBroadcastReceiver.onReceive() and near GoogleCloudMessaging.register() call
  • Log your registration ID! No one would be able to send pushes without, but it will allow you to test pushes with release builds.
  • Remember that sending GCM pushes is as easy as calling REST API. Keep scripts you can use for testing pushes in your code repository, so all developers and testers can use them.

Sample bash script you can use for sending pushes:


curl --header "Authorization: key=$SERVER_KEY" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send -d "{ \"data\" : {\"foo\": \"bar\"}, \"registration_ids\":[\"$REGISTRATION_ID\"] }"

And some development tip: remember to obtain new GCM Registaration ID each time your application is updated or restored – see GCM Advanced Topics doc page for more details!


  • Add proper logging! Log moment when you call registerForRemoteNotificationTypes / registerUserNotificationSettings, log each call of application:didRegisterUserNotificationSettings:, application:didRegisterForRemoteNotificationsWithDeviceToken:, , application:didFailToRegisterForRemoteNotificationsWithError:, application:didReceiveRemoteNotification:fetchCompletionHandler:, application:handleActionWithIdentifier:forRemoteNotification:completionHandler: and application:didReceiveRemoteNotification:
  • Log your APNS token! NSLog(@”APNS registered: %@”, deviceToken); in application:didRegisterForRemoteNotificationsWithDeviceToken: can save you a lot of time. Remember that without SSL push certificate, no one will be able to send pushes to your app.
  • Explain difference between APNS production and development environments to backend developers. Using production APNS environment with ad-hoc builds is not obvious – I saw many times staging back-ends configured to use development APNS, and hence not working with ad-hoc builds. Showing devs Apple docs often help here.
  • Have (at least) three environments: production, staging and develpment. This will allow you to distribute staging buidls to your clients and testers, while allowing you to test pushes on iDevices connected to your XCode in development environment.
  • Use tools that will make sending pushes as easy as invoking one script, and keep this script with APNS certificates in source code repository, so all developers and testers can use them. At CodingFingers we use ruby houston gem for testing!

Sample ruby script you can use to test pushes:

require 'houston'

# Environment variables are automatically read, or can be overridden by any specified options. You can also
# conveniently use `Houston::Client.development` or `Houston::Client.production`.
APN = Houston::Client.production
APN.certificate = File.read("certificate.pem")

# An example of the token sent back when a device registers for notifications
token = "<aacef01b 355909b4 61f6db41 fda99720 05f0bbe7 0b078d9d ac0d5560 e3452705>"

# Create a notification that alerts a message to the user, plays a sound, and sets the badge on the app
notification = Houston::Notification.new(:device => token, :badge => 6, :sound => 'default', :aps => { 'alert' => { 'loc-key' => 'LOC_KEY', "loc-args" => [79, "username", 55, "#foo"] }})

# And... sent! That's all it takes.

To use it, just properly export and convert your APNS certificate – you can find handy guide here

Posted by: Marcin Łępicki, https://github.com/mlepicki