Unit Testing a Bundle in Xcode
Apple's Xcode now has unit testing built in using OCUnit. While it's a little complicated to get set up, they do provide decent instructions on how to add unit tests to your projects. The recommended setup is to use what's called a "depenendent" target, where tests are executed at build time by doing some fancy bundle loading. Unfortunately, they only tell you how to do it for applications or frameworks. If you're writing a bundle, for example a Dashboard Widget plug-in, it is still possible to setup a dependent target, it just takes some more fussing around.
Update: This doesn't work in all cases. See part 2 for a better method.
You want to follow Apple's instructions, as if you were testing a framework. This means assigning the "Bundle Loader" setting to the path of your bundle:
$(BUILT_PRODUCTS_DIR)/MyBundle.bundle/Contents/MacOS/MyBundle
This checks unresolved symbols against your bundle, as if it were a dynamic library. Do not specify a "Test Host" setting, just as if this were a framework. At this point, you should be able to build and link against the test targer. Since this is a dependent target, it will also try to run your tests. You will, however, get "selector not recognized" runtime errors, since your bundle does not get loaded. To fix this, first add your bundle (MyBundle.bundle
) to the unit test target, so it gets copied to the "Resources" folder. Next you will need to load your bundle before the unit tests start running. You can do this by creating a "BundleLoader" class in the unit test target, and load the bundle in it's initialize
method:
@implementation BundleLoader + (void) initialize { NSBundle * myBundle = [NSBundle bundleForClass: [self class]]; NSString * bundlePath = [myBundle pathForResource: @"MyBundle" ofType: @"bundle"]; NSBundle * bundleToLoad = [NSBundle bundleWithPath: bundlePath]; NSAssert(bundleToLoad != nil, @"bundleToLoad should not be nil"); [bundleToLoad load]; } @end
Voila! This works because initialize
gets called before any test methods do, and thus resolves the run-time errors.