Install this theme
iOS Unit Testing: Spring ahead, Fall behind

Once upon a time I worked on an application that used dates. Tens of thousands of dates at a time, across different timezones. Each Spring there would be a flood of date related bugs from our QA testers and it would happen again each Fall. Here in the US we lose an hour in the Spring and gain it back in the Fall for Daylight Savings.

Making it testable

Imagine a model object class that looks like this:

-numberOfDaysInThePast calculates how long ago the eventDate is from the present in days. The implementation of that method looks like this:

This looks simple, and is actually just copied from several Stack Overflow answers.

Testing this code is difficult. The implementation has a hidden dependancy on the current system time in [NSDate date]. To test this we want both eventDate and the current date to be testable values. In order to do this we will modify the implementation slightly:

<code data-gist-id=“ae31164fe4943b2cd679” name=“numberOfDaysInThePast2”>

Now that hidden dependancy on [NSDate date] is still there, but it’s inside a method we can override. To do so in a test we will use a technique called ” extract and override to test inside the we will create a subclass of serve as our fixture. be overriden return value can against. in this example just make it property:>

Within our test case we can now use that subclass to test with known values for -currentDate :

Inside the test we’re following best practices for dealing with dates and creating a date just before a Daylight Savings change date for the timezone and calendar we’re testing with. We then create a second date that is some number of calendar days after that date.

Running the test shows that indeed the implementation of -numberOfDaysInThePast is the problem. The date calculation it is using is incorrect. If you deal with dates in your application I strongly suggest watching the WWDC 2013 session “Solutions to Common Date and Time Challenges”.

The Extract and Override technique for testing can be very empowering and is common in many languages. For whatever reason, many of the Objective-C and Swift developers I know are not aware of it. When using a private subclass as a test fixture like this it’s best to keep the overrides minimal and focused - don’t create a single class where everything can be overriden or set, instead prefer creating as many subclasses as you need with one change in each.

 
Blog comments powered by Disqus