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

Asynchronous Networking Approaches…

How should Asynchronous Networking be handled? This is quite a common question in various places, starting from interviews to forums like Stackoverflow. Yet, this is not a question to be answered in a sentence. There are several ways with their own strengths and weaknesses. This article is a humble effort to outline them all.

NSURLConnection Approach – New approach

The most modern of the approaches would be to use sendAsynchronousRequest:queue:completionHandler:
Following is an example of the usage of the method:

This approach has the following benefits:

  1. This does away with the repetitive code that handles intermediate results
  2. Race conditions are avoided which sometimes occur if using NSURLConnection delegates, as some of the part of the delegate gets prematurely released. The block here is retained
  3. In case of multiple asynchronous request, the code for handling each of the response is cleanly separated and thus less chance of mixup

But all these good things comes with a price tag.

  • You lose some control over the operations. Imagine the scenario when you will need to cancel the download of a large chunk of data. In the above implementation, there is no way you can actually cancel the request without leaking memory.

You can probably try cancelling the NSOperation within the queue that is sent as a parameter to the method, but that does not necessarily cancel the operation. It merely marks the operation as cancelled so that when you query the isCancelled property of the operation you get back a positive. But you will have to cancel all your activities yourself based on this isCancelled flag.

  • As stated in the first beneficial point, you can not handle intermediate results.
  • With this approach when a request is made, it either fails or succeeds, and it fails even for authentication challenges.

NSURLConnection – Traditional Approach

Then there is the traditional approach where we implement the NSURLConnectionDelegate methods and initiate the request with NSURLRequest. A quick example follows:

One benefit of using the traditional approach with NSURLConnection is that you get to handle authentication challenges through delegates. Though handling authentication challenges properly might be a lengthy and difficult, but it is nonetheless possible.

Following is the delegate method which handles authentication challenge:

But if there are multiple requests, then in the authentication challenge handler it becomes difficult to understand for which request the authentication challenge is thrown.

A Better Approach – NSURLSession

As we discussed both of the above approaches has their pros and cons. So, Apple has come up with an approach which takes the best of both. This is the approach with NSURLSession

Block based approach

Delegate based approach

Finally, the best approach in my humble opinion, would be to use AFNetworking, or RESTKit. There are other third party APIs too, like MKNetworkKit etc. I have not used MKNetworkKit by Mugunth Kumar, but the other two are really good when it comes to asynchronous networking and a myriad of other related features.

With AFNetworking, the above task can be performed as:

AFNetworking also allows to track progress with multipart request. The following is an example of an upload task with progress indicator:

iOS Development

Future

Recently we have been experiencing a lot of visions – visions that promise to change the world, visions that promise to metamorphose the living real world as we know it, into something sci-fi. Beautiful girl walking through the streets with transparent virtual screens in her front displaying critical information (there goes the chance for boys looking at her face, sympathy!), people waking up in the morning as the glass window changes its colour from opaque to transparent to let the sunlight come in and wake them up (is there an option to override this? I only slept at 3 o clock!), cars having sleek glass dashboards that displays every information the driver needs (or does not) to drive the car. All of these fancy stuff is mesmerising us, inspiring us to create something that will change the world. And like God’s approval to this change, futuristic technologies are becoming open sourced, letting millions of developers being empowered to take up the responsibility to change the world. Now people cannot say – “I wanted to change the world, but God did not make it open source!”.

So, it is a golden era or technology. The digital age. But what’s the future? We are living it now. Every single day we live the future of yesterday, is that not? I remember watching “Minority Report” with my wife (then girlfriend) back in Kolkata and never did it cross my mind to replace the face of Tom Cruise with Pranav Mistry (they don’t look alike at all!). But it’s the present. And as the saying goes – “Yesterday was history, tomorrow is a mystery. But today is a gift. That’s why it is called “Present (Thanks to Kung Fu Panda movie)”. We are experiencing the gift.

But when talking about future, it’s quite difficult to describe. At least now. Because, we would be talking about the future of future! Well, who will stop us to speculate? One interesting trend I have observed is – when some new technology or gadget comes into market, people become obsessed with it. People work for it, instead of – it working for people. Remember the time, when iPhone came into market? People were creating apps for iPhone. By this, I mean, apps that will look great in iPhone, perform great in iPhone, “Consumers will have an engrossed experience when playing this game in iPhone” – was what developers and marketers were saying. But now, people have come out of that obsession. Now, apps are being created leveraging iPhone. “Leverage” is not a respectful term. If you respect Mercedes Benz S Class, you cannot “leverage” that to do something. So, people balanced themselves, not being disrespectful as well as “leveraging” the new technology is what they did. Similarly, we can speculate the future is — leveraging “surface technology” people may be doing something in near future. Just an example! But more and more people are coming out of devices – “engrossed” is not a word they are looking for anymore, “Virtual Reality” is now a historic term. People want Augmented Reality. People love their world, and want to fill up its limitations with augmented information. The applications that the future will offer will relate to this. Be it the sixth sense technology, be it the classic Augmented Reality.

The most beautiful God gave us, is our mind. (heart does not do anything other than keeping you alive – biologically speaking). What’s the second most beautiful one? What did you say? – Eyes? Hmm… I respectfully disagree. The second most beautiful thing is – arguably—our hands. People can perform tremendous variety of work with the two hands. Using their hands, people want to feel the world, touch the world, understand the world. Hands gives us perception, drives us to imaginative thinking. Steve Jobs, may he rest in peace, respected hands. Here came the iPhone. So, the future of future will speculatively, take the experience out of the cheap or expensive gadgetry – take to the real living world. People will use applications which will be experienced with all 5 senses, (read that — 6 senses) into the real world. That will be the future. Have you ever seen an app which will let you taste a recipe? An app that will let you smell the beauty of a flower? Future will bring that to you. As a bottom line, in future people will satisfy their six senses with a surrogate army of applications which will live among us in the real world. That’s where we will be going.

What did you say? Impossible? Let’s hear your side of the story.