Trust, but verify.

President Reagan, for all his faults, gave us a very useful aphorism in describing his approach to diplomacy with the Soviet Union: “Trust, but verify.” This is also a very useful approach to take when writing unit tests when you’re working with a framework, particularly when you’re developing a human interface.

For example, Cocoa uses the target-action pattern for controls. When you create an NSButton you can specify which object to send a message to when it’s clicked — the target — and what message to send — the action.

You can trust that when you click the button, Cocoa will cause the action message to be sent to the target object so long as they have been properly specified. Therefore you probably don’t need to write a unit test that simulates clicking on the button. However, you should verify that your button has had its target and action properly specified, and you can write a test for this.

You can also apply this principal in your own code. Let’s say you’re implementing a new type of control that also has to follow the target-action pattern. In the tests for your control itself, you probably will want to simulate the appropriate user-interface events and see that a testing instance of your control behaves appropriately. However, you don’t need to do this in the code that uses the control — you can trust that the control behaves correctly due to the tests you wrote for the control itself, and just verify that it’s been properly configured.

Xcode: Unit Testing

Xcode 2.1 introduced integrated unit testing to the Xcode IDE. Xcode includes two unit testing frameworks, target templates for setting up test bundle targets, and infrastructure for running unit tests every time you build your project and reporting their results in the Build Results window just like compilers and linkers do.

With Xcode unit testing, you group your test cases into test bundles which are built by separate targets. This means that you don’t need to build two versions of your software — one with tests and one without tests — and can run your tests against the actual software you want to deliver.

Xcode 2.1 and later include OCUnit for unit testing of Objective-C Cocoa software, and it includes a new framework called CPlusTest for unit testing of C++ software. Using either you should be able to test C code with relative ease. Corresponding target templates are included for creating unit test bundles appropriate for Cocoa and Carbon applications and frameworks, and file templates are included for creating OCUnit and CPlusTest test case classes.

The test bundle target templates have a shell script build phase at the very end that invokes /Developer/Tools/RunUnitTests. RunUnitTests looks at the build settings it’s passed via its environment and determines from that information how to run the tests in your test bundle.

If you’re testing a framework, RunUnitTests will run the appropriate test rig and tell it to load and run the tests in your bundle. Since your test bundle should link against your framework, your framework will be loaded when the test rig loads your bundle.

If you’re testing an application, you need to specify the application as the Test Host and Bundle Loader for your test bundle in its configuration’s build settings. The Bundle Loader setting tells the linker to link your bundle against the application that’s loading it as if the application were a framework, allowing you to refer to classes and other symbols within the application from your bundle without actually including them in the bundle. The Test Host setting tells RunUnitTests to launch the specified application and inject your test bundle into it in order to run its tests.

There’s even support in RunUnitTests for invoking a test rig of your own, rather than the test rig for one of the supplied frameworks. You just need to specify the Test Rig build setting for your test bundle; this should be the path to a tool to run. It will be passed the path to your test bundle as its first argument, and if it needs to generate failure information it can just generate it in a gcc/compiler-like format on stderr:

FailingTest.c: 10: error: (1 == 0) failed

This will cause it to show up in the Build Results window as an error, just like a compiler or linker error. You can see the RunUnitTests manpage for more information on the environment in which your test rig will be run.

There’s a great Unit Testing Guide on the Apple Developer Connection web site that has lots of information on getting started with Xcode unit testing. Check it out!

Xcode: Configurations

In case anyone hasn’t noticed, Xcode 2.1 shipped at WWDC on Monday. It includes a whole slew of new features. First and foremost is, of course, Intel support. Lots of people have said a whole lot about this so I won’t repeat it here.

The new feature that will have the most significant and immediate impact on developers’ lives is the switch from build styles to configurations.

In Xcode 2.0 and earlier, a build style was a collection of project-level settings that were overlaid on the settings for all targets in the project. For example, if you specified OTHER_CFLAGS="-DFOO=1" in a build style and OTHER_CFLAGS="-DFOO=0" in a target, the build style would take precedence when it was active and the compiler would be passed "-DFOO=0".

This was confusing: Build styles were edited by inspecting the target, and the OTHER_CFLAGS entry in the target settings showed up with a strikethrough when it was overridden in the active build style. This also caused problems for some developers who didn’t want settings from build styles overlaid on all targets in a project, and they particularly didn’t want settings from a build style in a project to override settings in targets in subprojects.

Configurations in Xcode 2.1 are just collections of settings. Settings in a target configuration override settings in the matching project configuration. Also, target configurations are by default self-contained, while project configurations default to being empty, which means by default you don’t have to worry about overriding at all. What’s more, configurations are applied by name when building subprojects — settings in the project you’re building don’t override subproject settings.

Editing build settings in Xcode 2.1 is a lot like editing build settings in Xcode 2.0 and earlier: You just select a target or the project and bring up its inspector, and build settings show up in the Build tab. You can select a configuration to edit, and you can even edit all configurations at once. This is very, very useful — often most of the settings for a target will be identical across Debug and Release configurations. The ones that aren’t show up in a mixed state.

(Did you notice I referred to Debug and Release configurations? That’s because Development and Deployment have been retired.)

You can even specify that a configuration is based on a text file of key/value pairs with the “.xcconfig” extension. So if you have collections of settings that you want to standardize on — for example, a suite of compiler error and warning flags — you can store them in files and check them into your source code control system separately from any projects. You can even copy or drag directly from the target/project inspector in Xcode and paste or drop in an xcconfig file!

WWDC 2005 Wrap-Up

WWDC 2005 is over, and *damn* was it a great week! Apple made some incredible announcements and shipped some incredible software, I got to see lots of old friends and make a lot of new ones, and I got to talk to lots of developers about things that I’m passionate about: Core Data, unit testing, setting up and streamlining your build process, and creating insanely great software to make users’ lives better.

It was a wonderful, wonderful time. Thanks to everyone!

Unit testing and Core Data

Mike Zornek asks about unit testing and Core Data. I’ve been meaning to write about this, so this is the perfect opportunity to do so.

Writing unit tests against your model and code that uses Core Data is easy. For example, it’s trivial to load your compiled model in a unit test:

NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];

Not only that, but you can introspect it:

NSArray *entities = [model entities];

And you can do this all the way down to the property level. This means that it’s possible to assert that your entire model is set up the way you expect it to be. For example, you can make sure that your Employee entity has a mandatory salary attribute with a minimum value of 1 and a type of NSDecimalAttributeType, and descends from a Person entity that has a mandatory name attribute with a minimum length of 1 and a default value of “name.”

But how do you test your use of Core Data? You just use Core Data in your tests as you would in your project. For example, to instantiate a complete Core Data “stack” (as it’s sometimes referred to):

NSManagedObjectModel *model;
NSPersistentStoreCoordinator *coordinator;
NSManagedObjectContext *context;

model = [[NSManagedObjectModel alloc] initWithContentsOfURL:urlToModel];
coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:coordinator];

To instantiate managed objects associated with that context from entities in your model:

NSManagedObject *employee;

employee = [NSEntityDescription insertNewObjectForEntityForName:@”Employee”
inManagedObjectContext:context];

This gives you an autoreleased Employee (assuming your context’s coordinator’s model has an Employee entity, of course). It’s that easy.

You can then do things like check that this object was created with the correct defaults (e.g. the ones specified in your model), that it posts KVO notifications properly for properties where you care about such things, and so on. You can even add a persistent store to the coordinator and test that saving and loading work (and don’t work when they’re supposed to fail, of course) just by using normal Core Data and Foundation APIs.

You can multiply the full power of data modeling with the full power of unit testing and test driven development. It kicks ass.

Core Data: Generating an interface for an entity

The new Core Data framework and Xcode 2 modeling tools in Tiger are an extremely powerful way to develop great end-user applications quickly. You can even easily generate a human interface for your application that will let you work with its data model with little to no code.

To generate an interface, create an empty window in Interface Builder and make sure you’ll be able to see it with Xcode in front. Switch to your model in Xcode. Then just option-drag the entity you want an interface for into your window. Interface Builder will ask you whether you want an interface for one or many instances of that entity, and then generate a basic form-style human interface for all of the attributes and to-one relationships in that entity.

This generated interface isn’t a special monolithic “NSCoreDataControl” or anything of the sort. it’s composed of standard Cocoa controls that wired to standard Cocoa controllers via bindings. If your nib file’s owner is set to be an instance of NSPersistentDocument or a subclass, Interface Builder will even bind the controllers’ managed object contexts to the document’s.

If you just want to create controllers rather than full interfaces, or if you want to update the controllers in your nib file with the latest definition of your entity, drag the entity from your model straight to your nib’s document window. (That’s the one with the tabs for classes and instances etc.)

Note that none of this, none of this requires generating or writing code. You can create a new Core Data Document-based Application from the project template, create a data model for it in Xcode, create an interface for it in Interface Builder, and then build and run it. You can create, save, load, and manipulate documents and even undo and redo changes and avoid saving invalid data with no code.

Code Width

There’s a question on wrapping code at 80 columns in the Joel on Software Forum. Most of the time, when I see 80 columns as a standard it’s to enable easy printing of the code. However, in this day and age, why are you printing code? I print code occasionally when I need to read it in-depth, but other than that I do most of my reading on-screen. It’s certainly not a regular occurrence.

I also use mostly large or widescreen displays for coding. The smallest display I use regularly is my laptop, which is 1152 by 768. Most of the time I use my 19-inch monitor, which I run at 1600 by 1200. As a result, if I want to write really long lines, I can. But I don’t.

I generally limit the length of lines I write to 80 to 120 characters. Most of the time this is easy, because Objective-C’s syntax lends itself to very readable multi-line expressions:

NSDictionary *d = [NSDictionary dictionaryWithObject:@"Chris"
                                              forKey:@"name"];

The main reason I do it, though, is that I use multiple windows while I code. I usually have at least 6 windows open in Xcode while I’m coding: The Xcode project itself, the source and header file for the class I’m working on, the source and header file for the unit test I’m working on, and the build results window (which also shows my unit test results). Often it’s much more, with more class and unit test sources & headers open. And it’s much easier to fit these windows all on a screen when they don’t need to be as wide as the screen to see their contents…

Joel Spolsky’s Bionic Office

In the latest installment of Joel on Software, Joel talks about his new office.

I like a lot of what he’s done with it. It’s largely the kind of space I’d design. I might or might not have private offices, now that I’m starting to buy into XP more, but I definitely like a lot of what I see.

This amused me, though:

> The monthly rent for our offices, when fully occupied, will run
> about $700 per employee. The build-out was done on budget and paid
> for almost entirely by the landlord. I suspect that $700 per person
> is on the high side for software developers throughout the world,
> but if it means we can hire from the 99.9 percentile instead of the
> 99 percentile, it’ll be worth it.

I strongly expect it’s actually on the low side, at least in large corporations.

Joel says each employee is getting about 425 rentable square feet, at a cost of $700 per month. That’s about $20 per square foot per year. That’s low for Class A office space, at least in some markets. Like, say, Schaumburg.

(Though with 53,255 square feet available in Zurich II, and a couple of newly-built office towers standing vacant, and a bunch of other Class A space vacant, perhaps Schaumburg rents have come down since I last looked in 2001…)

I knew it wasn’t all puppies and rainbows!

[Joel on Software][1], “[Local Optimization, or, The Trouble with Dell][2]”

> Unfortunately, the dirty little secret about Dell is that all they have
> really done is push the pain of inventory up to their suppliers and down
> to their customers. Their suppliers end up building big warehouses right
> next to the Dell plants where they keep the inventory, which gets
> reflected in the cost of the goods that Dell consumes. And every time
> there’s a little hiccup in supplies, Dell customers just don’t get their
> products.

This isn’t the only problem with Dell. Their other big problem is that they’re constantly starting price wars, which keep driving down their margins further and further, which makes not only their products but all of their competitors’ products crappier and crappier. It also fuels the delusion that price is the only factor that customers use when selecting a supplier. It’s a race to the bottom that nobody wins.

[1]: http://www.joelonsoftware.com/
[2]: http://www.joelonsoftware.com/news/20030115.html

Platform Futures

On Windows, many developers seem to want to run as fast as possible away from Microsoft Visual C++ and embrace Microsoft’s C# and .NET platform for new development. Most Windows developers that I’ve seen seem downright enthusiastic about these technologies. It’s disconcerting; I’m not used to seeing Windows developers (or users) be enthusiastic about their platform.

On the Mac, many developers are trying to hold onto C++ and Carbon for as long as they can, even for new development. A new Mac developer on the Carbon list actually said he wished Apple had a C++ framework that used MFC-like “message maps” for Mac OS X-only Carbon development “to make it easier to build software fast!” (Paraphrased.) And Metrowerks is spending money & time building a next-generation C++ PowerPlant framework for Mac OS X-only Carbon development! And some developers keep on Apple’s case to try and maintain feature parity between Carbon and Cocoa.

Fortunately, Apple isn’t giving in to them as much as they might think. For instance, WebKit has a Carbon wrapper, but it’s just a wrapper; WebView is really a Cocoa framework and if you want to extend it you’re going to have to use Cocoa. The Cocoa Controller layer is only really possible to do with a rich dynamic runtime; it’ll never make it to Carbon. You can only build screen savers using Cocoa and Objective-C. You can only build preference panes using Cocoa and Objective-C. Virtually all new applications coming out of Apple are built using Cocoa and Objective-C.

(Keynote, SoundTrack, LiveType, iCal, iPhoto, iSync, iChat AV, Safari… Final Cut and Logic don’t count, since they ware originally developed for the traditional Mac OS and thus aren’t new. Neither does Shake, since it was originally developed for Irix and X11 — though it wouldn’t surprise me at all to see it rearchitected as a Cocoa application in the next couple of years.)

The future of development on Windows is C# and .NET. This has been clear since Microsoft first released .NET, and it’s especially clear in light of the latest PDC and Longhorn.

The future of development on the Mac is Objective-C and Cocoa. This has been clear ever since Apple bought NeXT, and it’s especially clear in light of the latest WWDC and Panther.

Deal with it.