L'etat, c'est moi
Mere Complexities sells the consulting and development services of me, Paul Wilson.
Conferences
Archive
iPhone TDD using Google Toolbox and iphone_testify
Previously, we’d decided to switch from using Rbiphonetest to using Google toolbox for Mac code. It’s about time we got started.
To begin with we’ll just set up an iPhone project for testing. This will include automatically running all the tests every time – just like autotest.
Setting up the files
Of course you’ll need to be running OS X 10.5 (Leopard) and the latest iPhone SDK.
Fire up XCode and create an iPhone OS project. (For the purposes of this example it doesn’t matter what type; a Utility app is as good as any). I’ve written a Ruby Gem to help getting all the files in place, so we may as well use those. From the terminal go to your new application directory.
First we’ll install the gem. If you haven’t already you will need to to add github as a gem source. (If you can’t remember just enter gem source and see if github is listed).
sudo gem update --system
gem source -a http://gems.github.com
Either way, install the gem.
sudo gem install paulanthonywilson-iphone_testify
Then run the iphone_testify command.
iphone_testify
This adds the google unit testing code to the google_testing directory, creates a directory for the UnitTests. There’s also a Rakefile_ and an autoiphonetest.rb, and we’ll get round to those later.
Setting up XCode
There’s a few things you need to do in XCode. The gem doesn’t do this yet, but I’m working on it.
Create a new Target called Unit Test. Right click on Targets in the left pane. Choose an “iPhone OS” Application target and call it “Unit Test”.

Right click on the Unit Test target and choose “Add—> Existing Files”. Select all the files in the google_testing directory (or at least all the .h and .m files).

(If you’re feeling tidy, which I hope you are, you probably want to add these to a “google_testing” group as well.)
Right click on the Unit Test target again, to add a “new run script build phase”.

Set the script to be google_testing/RunIPhoneUnitTest.sh.

Add a group in which to keep your unit tests. Right click on the group and set the path to be UnitTests, so that the test classes will go where we expect on the file system.

That’s all a bit of faff. I am hoping to automate the xcode part: you can stay tuned by watching iphone_testify on Github.
Write a test
Let’s write a dummy test, just to get us started. Right click on your UnitTests group and add a new file (iPhone OS Cocoa Touch Classes – NSObject subclass). Let’s call it BlahTest.m. Add it only to the Unit Test target. Uncheck “Also create BlahTest.h”: you don’t need a header.

Edit the BlahTest.m to extend SenTestCase:-
#import "../google_testing/GTMSenTestCase.h"
@interface BlahTest : SenTestCase
@end
@implementation BlahTest
@end
Note that we’ve included the interface definition in the implementation file: there’s nothing to stop you using a separate header file, but there’s not a lot of point. Let’s add a failing test.
@implementation BlahTest
-(void) testSomething{
NSString *actual = @"hello matey";
STAssertEqualStrings(@"hi mate", actual, nil);
}
@end
Run through XCode
The tests are ‘run’ as part of the build and failures are reported as build failures. In XCode set the target to “Unit Test” and build.

Run through Rake and autoiphonetest.rb
Running iphone_testify also provides you with a Rakefile for building/running the test target. From the command line in your project directory just run
rake

Even better, run
./autoiphonetest.rb
This will build/run the unit tests evertime a change is detected in the Classes or UnitTests directory. The automatic running of unit tests does wonders for flow.
The rake and autoiphonetest.rb builds will inform you of the state of the tests using Growl: to take advantage of this you will need to have Growl and growlnotify installed. In order to work around a bug in growlnotify, you need to enable “Listen for incoming network connections” in the Network pane of the Growl System Preferences.
Now we’re set up running with autoiphonetest.rb, let’s fix our test and see our pass notification; I’ll leave the test fixing as an exercise for the reader.

That’s it for now. In our next instalment we’ll look at building up or Twitter application using Objective-C unit tests.
Update: Corrected a couple of bugs:
- The target must be called Unit Test (not Unit Tests) to work with my gem
- I ought to have used STAssertEqualStrings for comparing strings (not STAssertEquals).