Category Archives: OCHamcrest

Converting OCUnit to XCTest

My first attempt at converting a real project to XCTest in Xcode 5 went fairly well. The project was fairly simple, and had 582 OCUnit Application tests using OCHamcrest assertions. I performed this using Xcode 5 DP3, so the issues I encountered should have been fixed by the time you read this.
Xcode 5 supports both OCUnit and XCTest, so the app loaded and the tests ran ok. Interestingly, the Test Navigator displayed all of the OCUnit tests nicely. I had wondered whether or not the Test Navigator only worked with XCTests. It works with both though.
Once all the tests were passing, I then used the “Edit -> Refactor -> Convert to XCTest” menu option to convert the OCUnit test target to XCTest. I wasn’t sure what was going to happen, but had Git ready to undo any changes if/when things got messed up. It turned out that I didn’t need to do this.
The conversion worked almost perfectly. This isn’t a tough operation, basically just changing the #import from SenTestingKit to XCTest, and changing the test case class parent from SenTestCase to XCTestCase.
This conversion reused the same target, without renaming it. So things look pretty much the same in the Test Navigator before and after the conversion.
Then I tried to run the tests. I expected that the tests would fail, or maybe even fail to compile due to OCHamcrest. What happened though was that Xcode 5 crashed. However, upon restarting Xcode 5, I could then select to run the tests without crashing, but got a linker error.
The conversion operation did not add the XCTest framework to the converted target. It did remove the SenTestingKit framework though. So this is probably just a bug in DP3. I submitted radar 14470998 which is fixed in the latest code.
After adding XCTest to the test target’s link build step, all tests ran and passed!
I have wondered, and talked with other developers that I work with, about why Apple would simply rename SenTestingKit to XCTest. It doesn’t appear that much if anything is functionally different. I’ve come to the conclusion (and the hope) that this is just the beginning. Having a totally separate, new framework allows Apple to make changes and additions going forward, without worrying about breaking legacy SenTestingKit users. Let’s hope that this is a new start for unit testing support from Apple.

 

“Duplicate Classes with Same Name” Bug

I ran into the most puzzling issue this past week. While working with the new MMDrawerController package on Github (written by some friends here at Mutual Mobile), I ran into a situation where the test runtime believes that there are 2 separate classes, both named “MMDrawerBarButtonItem”.

The failing source code for the project is on Github in WhosWorkingOnWhat at commit c19a6a7de5cda609c75b70d93aed91687fdfcf00. You can uncomment the code in that commit to see that the log shows that there are 2 subclasses of UIBarButtonItem with the same name “MMDrawerBarButtonItem”.

What’s happening in testNavBarLeftButton is that the code under test assigning an instance of one class named “MMDrawerBarButtonItem” to the leftBarButtonItem. The test is then trying to confirm that an instance of the correct class has been assigned to the left button,  but when the test compares it with [MMDrawerBarButtonItem class], it is getting the second class with that name, and therefore failing the assertion!

This is a most peculiar bug, and so far has me completely stumped. Any ideas on how my tests are managing to create 2 classes with the same name?

Update 5/28/13:

Last week one of the senior iOS engineers ran into a similar problem on his project, and determined the cause and a workaround. The problem is caused by the combination of CocoaPods and OCUnit Application tests.

CocoaPods was used to add a 3rd party library. In my case, it is MMDrawerController, in his it was something else. Then in order to test code that interacts with that 3rd party library, the Podfile was updated to add the same library to the unit test target. And voila, when tests are run, 2 instances of the classes in the 3rd party library will exist in the combined product code + unit test code test target.

Normally the compiler and linker would detect this duplication, but no errors are generated  when the duplicates exists separately in the product target and the unit test target, which then get combined when running the unit tests.

My workaround was to simply stop using CocoaPods. My friends solution involved putting dependencies into a separate static library. There’s probably a better solution, and I’ll update this when it is identified.

First Observations on TDD with VIPER

In a previous post, I mentioned that I was rewriting WhatsMySpeed (now called HowsMyFuel and posted publicly on Github) using TDD and the VIP architecture. I’m committing changes at each step of the TDD cycle. I’m exploring to see if commit comments on Git can be used blog style. Let me know if this works for you.

One of the reasons in VIP of separating the ViewController into 3 components (ViewController+Presenter+Interactor) is to eliminate the Massive View Controller, so common in iOS apps. I’m discovering that one of the up sides to doing this is that I can move many of the unit tests from application to logic tests.

View controller tests typically require running in OCUnit application tests. OCUnit application tests are slower, since the app bundle is loaded. I don’t know how much slower yet, but I hope to test this later, as the number of unit tests gets larger.

So what goes into the View Controller vs the Presenter or Interactor? Normally the View Controller does nearly all the work. That’s why iOS view controllers tend to be huge. And huge typically means hard to read, even harder to unit test. However, I’m attempting to reduce the size and complexity of the view controller by removing all business logic. By that, I mean the logic that decides what an event does.

ViewController should contain basic iOS glue stuff; outlets, actions, etc.

Presenter should contain display-specific business logic, without interacting with the models.

Interactor should implement the business logic, aka use cases. It maps model data to the form needed by the Presenter and/or ViewController.

For example, the HowsMyFuel code as of April 25, 2013 contains code to register a tap gesture recognizer, and handle the tap event to recenter the map display when it is tapped. As is often the case, the event handling code is about 5 times the size of the business logic, which obscures the business logic, or intended behavior. To fix that, I’m going to elevate the business logic into the Presenter, where the expected behavior will be made crystal clear (when map is tapped, recenter the display on the user). Since this behavior is related directly to the UI display, I’ll put it in the Presenter. If it was dealing with Model data and/or not UI display specific, then I’d elevate it even higher to the Interactor.

One Unit Test Framework to Rule Them All

I kid myself about changing my mind daily regarding the “best” unit testing frameworks. I’ve been advocating for Kiwi for several months now. Well, here goes again.

Kiwi

Pros: I absolutely love Kiwi. It allows test to be well organized (RSpec style), has excellent mock support (including Class mocks), is fast, and is easy to use (runs on top of OCUnit logic tests), and has asynchronous support.

Cons: Debugging tests is difficult. Whenever I try to debug tests, I typically get dumped into assembler code. Yech!

Maybe I just don’t understand how to debug block code.

I’ve also been considering whether having disorganized tests is actually a symptom (smell) of having classes that are too big. I’ve been reviewing an associate’s code that uses OCHamcrest and Mockito, and I must say that I find it quite readable.

So, the current HowsMyFuel TDD project (April 22, commit 068c19d75e) fails unit tests, and it isn’t clear why. I could probably guess, and use trial-and-error to fix it, but I’d prefer to have a clear diagnostic approach to debugging and fixing tests.

So I’m going to rewrite the tests using OCUnit, OCHamcrest, and OCMockito and see if the error occurs, and if so, how tough it is to debug and fix.

VIP Architecture

One of the architects at work has started exploring using an architecture he is calling VIP (View-Interactor-Presenter?). He started thinking about this idea from reading an Uncle Bob blog entry on 8thlight.com. Yesterday he presented his ideas to the group during a brown bag session, and it got me thinking about the implications of such an architecture to unit testing.

The main idea is to abstract and extract use cases up out of the other components, primarily the view-controller, into a separate, simple NSObject called the Interactor. This object then deals with implementing use cases (aka business logic).

In a sense, the traditional MVC model becomes the Presenter component, used similarly as in an MVP architecture.

What about the Model? This is still a bit fuzzy in my thinking, but there can actually be two different types of model, and places where they exist. The Interactor interfaces with the traditional model, which could be CoreData, a RESTful API extraction layer, local persistence, etc. A key concept though, is that this Model uses fully abstracted, reusable objects, not customized for a particular presentation method or style.

Within the Presenter component, there may exist another presentation-specific model object that converts the reusable Model object into a form needed for presentation. Like I said, still too fuzzy of a definition, but it feels like a good starting point.

What does this mean, really? I think it means that business logic gets put into a single place, instead of being scattered around in various other places. The really big implication here is that the high level behavior of the system is defined in abstract terms in the Interactor! I think this makes it possible to do TDD starting with tests built from Use Cases, which I believe is the definition of Acceptance Test Driven Development (ATDD).

I’m going to start redoing my What’s My Speed sample app this weekend to see how well this concept works, hopefully firming up some of the fuzzy areas. In order to really test the ATDD aspects, I’ll need to start from scratch, creating and working from User Stories. I’ll be posting my progress as I go.

Update: I’m renaming the new code HowsMyFuel to avoid confusion with the older code. HowsMyFuel will use OCUnit, OCHamcreset, and OCMockito for unit testing. The code is posted publicly on Github.

Looking at Other Unit Test Tools: OCHamcrest, OCMockito, and Kiwi

I’ve recently started looking at other unit testing frameworks. I’ve been using OCUnit, GHUnit, and OCMock. But I’m finding that as my tests become more extensive and numerous, the tests themselves are becoming more difficult to read. I have been able to test everything that I’ve tried using these tools, but the resulting test code is sometimes hard to read. So my objective in looking at other tools is not for additional functionality, but for better readability.

The first tools that I looked at were OCHamcrest and OCMockito by Jon Reid. I like the syntax provided by these. But I ran into a problem when converting some of my tests because they currently use partial mocks. It appears that the Java version Mockito provides something like partial mocks, using what is called “spy”, but that this capability hasn’t been ported to OCMockito yet.

So while contemplating whether to try pushing forward using categories, swizzling, or subclassing to replace partial mocks, another iOS engineer recommended that I give Kiwi a look. So I did, and it looks very promising. I guess I haven’t given Kiwi a good look before because I heard that it was only for BDD, not unit testing. This turns out not to be the case.

I am going to give Kiwi a workout by converting the tests in one of the existing unit test files in What’s My Speed: the WeatherService. This file contains an assortment of OCUnit tests using both mock and partial mock OCMock objects.

Adding Kiwi to the project and file

The first step is to add Kiwi to the project. I’m going to just add the static library and headers, but there are instructions for adding it as a subproject. I built the code from source following the instructions on the Kiwi website. I then added the static lib and headers to the project, added the Kiwi headers directory to the test target headers search path, and then the kiwi.h to the WeatherServiceTests.m file:

#import "Kiwi.h"

I’m going to try leaving OCMock in the file until all of the tests have been completed. Then rebuild to verify everything ok.

Note: I had to clean and build twice before it would build without errors. This is a long time Xcode bug. Sometimes Xcode appears to cache things. Upon making changes to header paths and such, it sometimes takes a couple builds before strange errors go away. In this case, it was reporting that it couldn’t find WeatherService.h. Build cleaning and rebuilding twice and the reported error went away.

I also encountered an error with missing header files, including NSObject+KiwiSpyAdditions.h. It appears that building Kiwi inside the Xcode IDE results in only part of the header files being copied to the build directory. I fixed this by manually copying the headers from the Kiwi/Kiwi source directory to my project’s Kiwi headers directory.

Converting the first few simple tests

Next I’ll convert the first few tests. These are simple tests that verify the basic singleton operation of the object. So here is the existing tests before converting. I’ve removed some lines that aren’t related to these tests, and I’ll add them back as we go.

#import <SenTestingKit/SenTestingKit.h>
#import <OCMock/OCMock.h>
#import "WeatherService.h"
#import "WeatherService-Private.h"

@interface WeatherServiceTests : SenTestCase

@property (nonatomic, strong) WeatherServiceForTesting *weatherService;

@end

@implementation WeatherServiceTests

- (void)setUp {    
    self.weatherService = [[WeatherServiceForTesting alloc]init];
}

- (void)tearDown {
    self.weatherService = nil;
}

- (void)testInstantiation {
    STAssertNotNil(self.weatherService, @"Test instance is nil");
}

- (void)testSharedInstanceNotNil {
    WeatherService *ws = [WeatherService sharedInstance];
    STAssertNotNil(ws, @"sharedInstance is nil");
}

- (void)testSharedInstanceReturnsSameSingletonObject {
    WeatherService *ws1 = [WeatherService sharedInstance];
    WeatherService *ws2 = [WeatherService sharedInstance];
    STAssertEquals(ws1, ws2, @"sharedInstance didn't return same object twice");
}

Ok, pretty straight forward tests, no mocks needed. Let’s convert these to Kiwi:

#import <SenTestingKit/SenTestingKit.h>
#import <OCMock/OCMock.h>
#import "WeatherService.h"
#import "WeatherService-Private.h"
#import "Kiwi.h"

SPEC_BEGIN(WeatherServiceKiwiTests)

describe(@"Singleton (by choice)", ^{

    it(@"should instantiate using init", ^ {

        [[[WeatherService alloc]init] shouldNotBeNil];
    });

    it(@"should instantiate using sharedInstance", ^{
        [[WeatherService sharedInstance] shouldNotBeNil];
    });

    it(@"should return the same instance twice using sharedInstance", ^{
        WeatherService *a = [WeatherService sharedInstance];
        WeatherService *b = [WeatherService sharedInstance];
        [[a should] beIdenticalTo:b];
    });

    it(@"should not return the same instance twice using init", ^{
        WeatherService *a = [[WeatherService alloc] init];
        WeatherService *b = [[WeatherService alloc] init];
        [[a shouldNot] beIdenticalTo:b];
    });

});
SPEC_END

Now let’s test to make sure the tests are actually working. Cmd+U to execute tests, and everything appears ok. Are the tests actually working? To verify this, I reverse the test logic by replacing “should” with “shouldNot”, and “ShouldNotBeNil” with “shouldBeNil”, rerunning the tests I see the failures. So I have some confidence that the tests are doing what I expect them to be doing.

Our next test methods further verify that init is doing what we expect. It calls 2 other methods, that each do just one thing.

- (WeatherService *)init {
    self = [super init];
    if (self) {
        [self startTimer];
        [self updateWeatherInfoForZipcode:kDEFAULT_ZIPCODE];
    }
    return self;
}

Ok, so with OCMock we used a partial mock in two tests:

- (void)testInitCallsStartTimer {
    id mock = [OCMockObject partialMockForObject:self.weatherService];
    [[mock expect]startTimer];
    id __unused initedMock = [mock init];
    [mock verify];
}
- (void)testInitCallsUpdateWeatherInfoForZipcode {
    id mock = [OCMockObject partialMockForObject:self.weatherService];
    [[mock expect]updateWeatherInfoForZipcode:kDEFAULT_ZIPCODE];
    id __unused initedMock = [mock init];
    [mock verify];
}

Since Kiwi appears to have great support mocks, this should be pretty straight forward. Note that Kiwi’s mock support allows defining stubs and expectations on both mocks and objects. This eliminates the need for partial mocks altogether!.

describe(@"init", ^{

    it(@"starts the timer", ^ {
        id weatherService = [[WeatherService alloc]init];
        [[weatherService should] receive:@selector(startTimer)];
        id __unused initedMock = [weatherService init];
    });

    it(@"updates the weather info", ^{
        id weatherService = [[WeatherService alloc]init];
        [[weatherService should] receive:@selector(updateWeatherInfoForZipcode:) withArguments:kDEFAULT_ZIPCODE];
        id __unused initedMock = [weatherService init];
    });

});

Ok, this new code looks pretty similar. It’s shorter by one line because [mock verify] isn’t needed. And for this small set of fairly simple tests, the difference in readability isn’t much, but I’m seeing the potential for greatly improved readability. The structure of the tests feels much more organized. I need to learn how to really take advantage of that. I’m going to stop this blog here, and continue converting the rest of the tests to Kiwi. I’ll probably have more to say about this in future posts as I learn more about using Kiwi.