Some time ago, in a blog far, far, away, I wrote about unit-testing Core Data. Essentially, your test case class should create a temporary, in-memory Core Data stack in -setUp, and clean it up in -tearDown. Your test methods can access the temporary context, model and persistent store to investigate the behaviour of objects under test.
The thing is, with any non-trivial Core Data app you’re going to end up with multiple entities, each with its own suite of tests. Wouldn’t it be nice if Xcode could set that stuff up automatically?
Oh, right, it can :-). The template header is class.h:
// // «FILENAME» // «PROJECTNAME» // // Created by «FULLUSERNAME» on «DATE». // Copyright «YEAR» «ORGANIZATIONNAME». All rights reserved. // #import <SenTestingKit/SenTestingKit.h> @interface «FILEBASENAMEASIDENTIFIER» : SenTestCase { NSPersistentStoreCoordinator *coord; NSManagedObjectContext *ctx; NSManagedObjectModel *model; NSPersistentStore *store; } @end
And the implementation, class.m:
// // «FILENAME» // «PROJECTNAME» // // Created by «FULLUSERNAME» on «DATE». // Copyright «YEAR» «ORGANIZATIONNAME». All rights reserved. // «OPTIONALHEADERIMPORTLINE» @implementation «FILEBASENAMEASIDENTIFIER» - (void)setUp { model = [[NSManagedObjectModel mergedModelFromBundles: nil] retain]; coord = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: model]; store = [coord addPersistentStoreWithType: NSInMemoryStoreType configuration: nil URL: nil options: nil error: NULL]; ctx = [[NSManagedObjectContext alloc] init]; [ctx setPersistentStoreCoordinator: coord]; } - (void)tearDown { [ctx release]; ctx = nil; NSError *error = nil; STAssertTrue([coord removePersistentStore: store error: &error], @"couldn't remove persistent store: %@", error); store = nil; [coord release]; coord = nil; [model release]; model = nil; } @end
Put those in a folder called /Library/Application Support/Developer/Shared/Xcode/File Templates/Thaes Ofereode/Objective-C test case class (Core Data).pbfiletemplate
, along with a TemplateInfo.plist file that looks like this:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CounterpartTemplateFile</key> <string>class.h</string> <key>Description</key> <string>A subclass of SenTestCase, with optional header. Automatically sets up a managed object context suitable for unit-testing Core Data entities.</string> <key>MainTemplateFile</key> <string>class.m</string> </dict> </plist>
Xcode will automatically pick up the template the next time you use the template chooser.