iOS Development

Swift 2.0 and Unit Testing

Preface

As we mature, as programmers and professionals, we see things differently. Our approaches and perspectives change and our paradigms shift. We start weighing things on a different scale, silently laughing at our follies we made in adolescence. I admit, initial days of my journey as a programmer, I used to program like an artist. I would make a basic structure first, then perfect it slowly towards the requirement by debugging and thus narrowing the gap between the current and target state. It had been working fine, but the biggest problem with that approach was — debugging almost always takes up more effort and time than actual development. Though I love debugging, but also, in many cases, I was having to change a lot of code to make things optimized, which could be avoided by a preplanning the coding approach which is evidently lacking in the current modus operandi.

Then I got introduced to Test Driven Development (TDD) approach. I wouldn’t say that I was in love with the approach at the first instance and started following that everywhere — no. Apart from the fact that like most daytime programmers I do not have the luxury to follow any new approach as soon as I encounter, I actually was skeptic about the approach and never thought it to be practical. However, I decided to give it a fair chance and tried it out on a couple of home grown projects, and I liked it. Lot less debugging, hugely less worry about changing code and its impact, and lot less effort to develop.

Today’s post is not about TDD, but actually about Unit Testing. In the past days, writing a unit test for the piece of code written by the developer seemed impractical and frown upon by the developers and major part of unit testing was done manually by the developer before handing over to the QA team. However, as I mentioned before, the programming community is now matured enough not to ignore the boons of unit testing. Apple’s flagship IDE Xcode comes with XCTest unit testing framework bundled within. We will dive into the framework and testing techniques in this post.

What is Unit Testing

In the term Unit Testing, unit represents the smallest possible testable bit of code written. It might be a method, a class or a whole functionality, based on the viewpoint of the programmer. A test is a piece of code that exercises the code written to make an app, a library or a functionality and provides a status of pass or fail based on some given criteria. The pass and fail of a test is derived by checking for correct state of certain objects that are expected to change their states after an operation is done, or whether a piece of code throws an exception based on a specific set of data that passes through it where it is supposed to throw the exception. There are performance tests too, which measures the execution time of a set of code block and determines the pass or fail status based on preset benchmarks.

Different types of Unit Testing

As the unit testing frameworks matured, more and more types of unit testings were made possible. Along with the functional testing framework, non-functional unit tests such as Performance Testing were made possible in the unit testing frameworks. In Xcode 6, Apple introduced performance testing capabilities in it’s XCTest framework. In Xcode 7 they introduced UI Testing. We will dive into each type of testing one by one and see how this can be done.

Setting up Unit Test Project

I will use Xcode 7.0 beta (7A121l) for demonstrating the Unit Testing. When a project is created using Xcode it also sets up a Unit Testing project with it if “Include Unit Tests” checkbox is checked.

Screenshot_8_10_15__11_36_PM

Once the project is created, you will find a Test folder is created alongside with it too. Now we will see how we write tests. TDD approach talks about writing the test cases before you even start writing code. This approach asks you to write test cases for the code that does not exist and run the test case which fails. Then write the code to make it pass. However, here, for the sake of simplicity and for the sake of the very basic nature of the post, I will show a basic test scenario based on the code already written.

Main Project

So, I will start with a very basic project I created just for the demonstration purpose of this article called BookCatalog. The project is actually a slight variation of the time stamp sample project you get when you create a master detail project for the first time. So you have a plus button at the top and tapping that the table gets populated with name of books from an array which contains names of books and their authors.

Simulator_-_iPhone_6_-_iPhone_6___iOS_9_0__13A4305g_

So to demonstrate how tests work, I take an example of a method called "populateBookModel". The method looks something like below:

The above code actually parses the above array, populates the Books model.

Test Project

So, I would like to test this populateBookModel method to check whether the books are getting populated nicely. So, I would create a file in the test project with a name which signifies the class I am going to test. This file will contain all the tests for all the methods/functionalities I like to test from the MasterViewController class. Now I have to decide how to verify that the method actually executed without any problem? If you examine the code of the MasterViewController as displayed above, you will find that I actually take the books from books array and populate them into bookObjects array. So, if I check the count of these two arrays and they match, that would indicate that the population was successful. To achieve this, I write the following test —

If you execute the above test, the test will pass as the count of the books array matches with the count of bookObjects. So, the above test says that the population was successful.

Sample Project

I have put together a project which shows how to setup your unit testing project and write unit tests. All the examples in this article can be found there. You can grab the project at this location.

Conclusion

Unit Testing is a vast subject. With this article, I have touched the tip of the iceberg — because I wanted to write down my learnings as fast as possible. As I go on exploring more I will post more articles on unit testing. I hope the post was helpful and interesting to you and you will love writing unit tests as much as I do now. Please feel free to post comments and suggestions as always!

Advertisements
iOS Development

Apple Watch Notifications

Remote and local notifications are not at all a new thing. From the very day – the 17th of June, 2009, they were introduced, they have always been, arguably, the most favourite mechanism to deliver messages to the user. The messages has ranged from proximity alert to a store, new update to an app, directional instructions to illegal promotions.

 But in Apple watch, notifications take a new dimension. From the way the notifications are designed for  Watch, it appears quite evident that Apple has spent considerable amount of energy to make them better and more meaningful. Following is the flow showing how a notification is presented to an  Watch user.

  1. According to the  Watch Human Interface Guidelines and WatchKit Programming Guide, when an app running in the iPhone receives a notification, iOS decides where to show the notification. Though this is kind of a vague statement, but as of now there seems to be no control over this even if we specifically need the notification to be shown in  the  Watch. Also, I could not find any information on how iOS decides to show the notification where it decides to show. Guess we’ll have to wait a bit for to know that.
  2. If the notification is sent to the  Watch, the user feels a subtle vibration on his wrist or a mild audio cue based on the notification’s payload.
  3. Alarmed, as the user raises his hand, a very minimalistic screen is presented which is called Short Look interface. This is an immutable, non-scrollable screen that conveys the user the most important information about the notification. iOS designs them based on a predetermined template and present on the screen. This is  Watch’s interpretation of your everyday notification, with just a title provided by you in the notification payload.
  4. All work and no play makes Jack a dull boy. Who understands this better than Apple? So, here is the shining playful part. The customisable, scrollable, actionable notification screen. After the Short Look notification is displayed, if the user continues to keep his hand raised (in the hope that something else will happen…soon…well..anytime now…), or taps on the Short Look interface the Long Look interface is displayed.

Apple has given you freedom within the aesthetic boundary to design the Long Look interface. You can add buttons and graphics and customise the behaviour when the user taps on it.

But what happens if you don’t provide the Long Look interface? Well, Apple has a backup plan. iOS displays a default interface with the app icon, title string and alert message. Tapping on it launches the app.

OK, so let’s not allow Apple to have all the fun and design our own Long Look interface!

A Long Look interface has three major parts —

  • The Sash at the top of the screen — this includes the title string and the icon of the app
  • The content — this is your playground. Add any graphics and buttons
  • The dismiss button — this is always present, added by the iOS, and dismisses the notification once tapped

 In the Sash section, as a third party developer, you have basic freedom. You can change the tint color and title of the notification.

In the content, you have much more liberty. You can modify and design the label to show your notification message. You can add buttons, but not directly. All the buttons should come in a specific format through a JSON payload that will invoke the notification. The SDK already generates one  such JSON payload file while creating  notification scene for testing purpose.

Screen Shot 2014-12-04 at 02.29.48Changing the alert, title and category controls what the notification screen will display.

As you see above, in the “WatchKit Simulator Actions” array is holding a collection of buttons in the form of dictionary which can be used to add/remove/modify buttons in the notification.

To create a notification, create a new project and add a new Watch Target as discussed in my previous post. This time keep the “Include Notification Scene” checkbox selected to include our notification interfaces.

Screen Shot 2014-12-04 at 02.35.44

Include all the necessary app icon images. Apple could not think of any more, so they want only the following few dimensions :

  • 29 X 29
  • 36 X 36
  • 58 X 58
  • 80 X 80
  • 88 X 88
  • 196 X 196
  • 172 X 172

Xcode will generate two extra interfaces for you in the interface.storyboard (other than the usual screen for your watch app) inside your project. They are —

  • Static Interface — A notification interface that can be configured design time. It is mandatory to keep this interface in your app bundle.
  • Dynamic Interface — A notification interface that can be decorated with dynamic data in runtime. This is not mandatory.

When running the app, iOS first looks for Dynamic Interface. If not found it falls back to Static Interface. If the static interface suffices your n0tification requirement, it is safe to delete the dynamic interface. Also, it can be explicitly instructed not to show the dynamic interface.

For the time being, lets change the Static Interface. What we are trying to do here is —

  •  show a notification stating that Japan is already enjoying the new year with an action button.
  • Tapping on the “View” button the app will launch and
  • display the current time in Tokyo

Now create a new scheme for notification and map the notification executable to that scheme to view the  Watch notification in iOS simulator.

Screen Shot 2014-12-04 at 03.07.07

Screen Shot 2014-12-04 at 03.07.28

Screen Shot 2014-12-04 at 03.15.01

If you build and run your app now, the default static notification screen will show. Take into notice that the message text, button text everything is being pulled from the JSON file that is included in the bundle.  you can try changing them to see if the change takes place in the notification.

Before we do some action, lets modify the JSON file to suit our needs by changing title, message and category. (Screenshot above) Lets name them as follows:

"aps": {
        "alert": "Japan is already celebrating new year!",
        "title": "Happy New Year!",
        "category": "NewYear"
    }

Also, in the Interface.storyboard file, select the “Category” under Static Notification Interface Controller and in the attributes inspector, change it to “NewYear”. Make sure that the category names are matching in the JSON as well as in the storyboard. Otherwise, the app will not build at all.

Now we want the user to tap on the button and make something happen. Let’s add a date label to the interface of the  Watch app which will display the date based on the timezone set. Hook it to the InterfaceController as dateLabel.

Inside the Interface Controller, we can handle the notification like so:

@IBOutlet weak var dateLabel: WKInterfaceDate!
override func handleActionWithIdentifier(identifier: String?, forRemoteNotification remoteNotification: [NSObject : AnyObject]) {

        if let id = identifier {
            if id == "firstButtonAction" {

                var plistKeys: NSDictionary?
                var timeZones: NSDictionary?

                if let path = NSBundle.mainBundle().pathForResource("Timezones", ofType: "plist") {
                    plistKeys = NSDictionary(contentsOfFile: path)!
                    timeZones = plistKeys!["TimeZones"] as NSDictionary?
                }

                if let dict = timeZones {
                    NSLog("%@", dict.valueForKey("Tokyo") as String)
                    dateLabel.setTimeZone(NSTimeZone(name: dict.valueForKey("Tokyo") as String))
                }

            }
        }

    }

Now build and run the app. At first it will show your designed screen. Tapping on the dismiss button dismisses the notification screen. Tapping on “View” button shows Tokyo’s current time.

Right now, the app is showing the static notification screen. If you want to show a custom dynamic notification with data that can only dynamically be passed into the interface, we need to modify the “Dynamic Interface”. The Dynamic Interface is controlled by the NotificationController.swift. If you navigate there, you will find two functions commented out

override func didReceiveRemoteNotification(remoteNotification: [NSObject : AnyObject], withCompletion completionHandler: ((WKUserNotificationInterfaceType) -> Void))

override func didReceiveLocalNotification(localNotification: UILocalNotification, withCompletion completionHandler: (WKUserNotificationInterfaceType) -> Void)

Uncomment the

didReceiveRemoteNotification(remoteNotification: [NSObject : AnyObject], withCompletion completionHandler: ((WKUserNotificationInterfaceType) -> Void))

and make sure that the completionHandler is set to be .Custom

override func didReceiveRemoteNotification(remoteNotification: [NSObject : AnyObject], withCompletion completionHandler: ((WKUserNotificationInterfaceType) -> Void)) {
        
        // Tell WatchKit to display the custom interface.
        completionHandler(.Custom);
    }

Now if we make any modification to the dynamic interface, you will see that the dynamic interface with its changes is being shown as the notification screen. This is because, as I mentioned earlier, iOS searches for the custom dynamic interface first. If it can not find one, then only it loads the static one.

Try changing the .Custom to .Default to see your static interface.

You can download the whole project from Github — https://github.com/an-indya/WatchNotifications

Hope you will enjoy building for  Watch as much as I did. I will try putting in something more as I learn. Please do leave a reply and feel free to share if you like!

Hope this helps!