Category Archives: Uncategorized

Asynchronous unit tests using XCTestExpectation

I came across an interesting blog post by Phil Beauvoir about Asynchronous Unit Testing in Xcode 6 using the new XCTestExpectation. It explains how he converted existing Objective-C asynchronous iOS unit tests to Swift, at the same time making them more efficient and readable by using an instance of XCTestExpectation and waitForExpectationsWithTimeout().

XCTestExpectation is a dirt simple class with 1 method: fulfill(). Create an instance of it and call fulfill() when the expectation has been met.

In your test assert section, call waitForExpectationsWithTimeout(), passing the XCTestExpectation, and Voila! Asynchronous unit tests.

As opposed to using a spin loop, this explicitly informs the XCTest framework that your test is waiting for an asynchronous event to happen, allowing it to perform other tests while waiting.

Using Kiwi for BDD plus TDD

This past week I helped out one of our large project teams to knock down their bug backlog. This was code that I hadn’t really worked with before. It was delightful to work with a state of the art, new code base that fully utilized great architecture (VIPER), Uncle Bob’s clean code practices, extensive unit test coverage using Kiwi and OCUnit, and automated UI tests using KIF. Understanding the code was easy, and locating the correct spot in the code needing changes was very straight forward, a result of both good architecture and clean coding. I was even more delighted to find that the code needing changes was covered with Kiwi tests. I absolutely love working with Kiwi (debugging difficulties aside). It is so incredibly flexible, just about any type of testing can be accommodated (ATDD, BDD, TDD). I still have a lot of room for improvement in my skills at combining all of these though, and am hoping to take my skills in using it to higher levels.

One of the things that occurred to me (I apologize if I’m late to the party on this one) is that ATDD/BDD style tests can be facilitated by creating helper methods to abstract actions, states, and setting up state such as displaying a particular screen. For example, firstScreenIsDisplayed, acceptButtonWasTapped, userIsLoggedIn:, and displaySecondScreen. These can all probably be added to a Wireframe object (in VIPER architecture). Doing this would allow BDD tests to be clearly written such as:

describe(@"First screen", ^{
   __block Wireframe *wireframe;
   wireframe = [[Wireframe alloc] initForTesting];      
   [wireframe firstScreenIsDisplayed];
   context(@"user is NOT logged in", ^{
      [wireframe userIsLoggedIn:NO];
      context(@"Accept button is tapped", ^{
         it(@"issues a notification to log in", ^{
            [[[wireframe should] receive] displayLoginNotification];
            [wireframe acceptButtonWasTapped];
         });
      });
   });
   context(@"user is logged in", ^{
      [wireframe userIsLoggedIn:YES];
      context(@"Accept button is tapped", ^{
         it(@"goes to second screen", ^{
            [[[wireframe should] receive] displaySecondScreen];
            [wireframe acceptButtonWasTapped];
         });
      });
   });
});

This is just a rough draft of code, and probably syntactically incorrect. I’m going to build some tests using this approach, and will clean up the syntax and provide some more detail as I work it out. For example, readability is better without beforeEach/All (and left out above), so I want to see which happens if code is inserted without one of these (I’m hoping the same as beforeAll).

OCUnit Logic Tests Are Dead

… long live OCUnit Application tests.

I’ve been espousing the use of logic tests for quite awhile now. But recently, I’ve had a chance to work with some projects that have a fairly large number of OCUnit application unit tests. To my surprise, these tests run very fast, roughly sub-second per hundreds o tests.

Of course, test execution times will vary depending on the individual project and tests, but it appears that in general, there’s no need to jump through hoops using OCUnit Logic tests, since simply using OCUnit Application tests should work just fine.

This also applies to GHUnit. I’ve seen a project with over 600 tests execute in under 2 seconds.

Anyone have observations that disagree with this?

 

HowsMyFuel Step 2: Time Display

Ok, so having created the basic app with a map view using TDD, the next step is to add a time display. Creating a time display is really easy in iOS. Doing it using TDD and a well planned architecture maybe not so easy.

Time events and information may be needed in several places in the app. In addition to simply displaying the current time, I may need time information to determine if/when I’ve stopped at a gas station. So I probably need a time service to provide time notifications than can be observed wherever needed. I could sprinkle NSTimer and NSDate code around the app wherever time info is needed, but that would be ugly, and violate the DRY principle (“Don’t Repeat Yourself”). In a TDD/unit tested environment, having a single copy of well tested code becomes even more of a benefit.

So I’m going to create a model object (eg MVC) to generate time notifications every second.

Next question: I’m going to need time formatted into a text string for display. Where should we put the text string formatting code? We’re trying to keep the ViewController thin, so that means moving it up into the Presenter (since it is UI related), or over into the Time model. So I ask myself the question: “In the future, when I’ve long forgotten how I implemented this code, where will I look for it?” In this case, there isn’t a clear answer. The Time model will generate notifications which the Presenter will observe, and the Presenter will then send a message to the ViewController to display/update it’s time display. The Time model needs to understand the NSTimer and NSDate classes, so maybe if I do the formatting in the Time model, I can relieve other objects from having to. So I’m going to include a formatted time string in the notifications that the Time model broadcasts. If more control, or multiple formats are need in the future, then I can easily extend the Time model to do so. For now, we’ll stick with the TDD concept of doing the minimum thing.

So to follow along in the code, refer to the Commit log on Github starting April 27, 2013.

 

 

Unit Testing Core Data

Ok, let me start by repeating one of my mantras: don’t unit test Apple’s code. We’re going to assume that Core Data works as designed. And we have pretty high confidence that this is the case because I have been told that the Core Data group actually unit tests their code.

What we need to unit test is the code that we write. I would also add to this that we should write tests for the Core Data boiler plate code. This is the code that is created by the Xcode project templates when we create a new project. I am fairly certain that Apple does not unit test their template code, judging by the times that unit tests fail to work upon a new release of Xcode. Since the boiler plate remains essentially the same for each project, it makes sense to create a reusable starting point project that includes unit tests and reuse that. I’ve created one of these for the Master-Detail Application and will be sharing it publicly once I decide how and where to put it. Even better would be a new set of project template files to do so, but at the rate that these change, I’m not sure I’m willing to sign up to do that 🙂

In the boilerplate Master-Detail application code, the Core Data stack is instantiated in the appDelegate. So the tests for that code should appear in the appDelegate’s unit tests file. Once again, let me state that we don’t want to test that Core Data works as intended. We want to verify that our code works as intended.

Graham Lee, author of Test-Driven iOS Development, discusses using unit tests to perform what I would consider Core data integration testing. This is good information, and I won’t duplicate that here. Go buy the book. But since one of the premises of unit tests is that they execute quickly, we need to consider carefully whether or not to use the actual data model during unit tests, or to delegate that to integration tests. This of course will depend on how big the model is. A good approach might be to use the actual data model, and if unit tests begin to take too long, then revert to a test model.

I’ll stop here for this post, and add notes regarding specific Core Data components going forward. Please feel free to drop me a note regarding your experiences with unit testing Core Data. Many developers believe that Core Data code cannot be unit tested. I’m on a quest to dispel that notion.