CoreDataを使う場合、Model(テーブル定義みたいなもの)を変更すると、
マイグレーションが走る。
例えば新しく追加されたカラムについてデフォルト値をどうするかなど。
それをGUIで設定できる反面、各モデルバージョンからのマージ内容を毎回作成しないといけないので、 必ず設定し忘れがある。
マージポリシーなど個別に実装すればよいのだが、ひとまずテストを書いて、 設定漏れがないようにする。
sqlitenの作成
dataに各モデルバージョンのsqliteを置いておく
Data1.sqlite (Version1)
Data2.sqlite (Version2)
CoreDataManager
CoreDataを扱うクラス
@interface CoreDataManager : NSObject
{
NSManagedObjectModel *managedObjectModel;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
}
@property (nonatomic, strong, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, strong, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (NSString*)storeDirectory; // 保存用ディレクトリ
Test
- テスト用の保存ディレクトリ作成
- テスト用のSQLのコピー
- マイグレーションテスト実行
- テスト用保存ディレクトリの削除 ※GHUnit + OCmockを使っています
テスト用の保存ディレクトリ作成を行う
テスト実行前にディレクトリの作成を行う
- (NSString*)testStoreDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return [basePath stringByAppendingPathComponent:@"core_data"];
}
- (void)setUpClass {
// Run at start of all tests in the class
// Store用ディレクトリ作成
NSFileManager* fileManager = [NSFileManager defaultManager];
NSString* storeDirectory = [self testStoreDirectory];
if (![fileManager fileExistsAtPath:storeDirectory]) {
NSError* error;
BOOL ret = [fileManager createDirectoryAtPath:storeDirectory
withIntermediateDirectories:YES attributes:nil error:&error];
GHAssertTrue(ret, @"create save dir");
}
}
テスト用SQLコピー
ファイル名をもらってコピーするmethodを作成
- (void)copySQLiteFile:(NSString*)filename
{
NSString* filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:filename];
NSString* storePath = [[self testStoreDirectory] stringByAppendingPathComponent:@"Data.sqlite"];
NSFileManager* fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:storePath]) {
[fileManager removeItemAtPath:storePath error:NULL];
}
NSError* error;
BOOL ret = [fileManager copyItemAtPath:filePath toPath:storePath error:&error];
if (!ret)
GHTestLog(@"error:%@", [error localizedDescription]);
GHAssertTrue(ret, @"copy file");
}
マイグレーションテスト実行
OCMockをつかって保存用ディレクトリを書き換えておく
- (void)testDoMigration
NSArray* tests
= @[
@"Data1.sqlite",
@"Data2.sqlite",
];
for (NSString* sqliteFile in tests) {
GHTestLog(@"sqlite file :%@", sqliteFile);
id mock = [OCMockObject partialMockForObject:[[CoreDataManager alloc] init]];
[[[mock stub] andReturn:[self testStoreDirectory]] storeDirectory];
[self copySQLiteFile:sqliteFile];
GHAssertNoThrow([mock doMigration], @"no throw");
// マイグレーション後のデータチェックとか
}
}
テスト用保存ディレクトリの削除
- (void)tearDownClass {
// Run at end of all tests in the class
// Store用ディレクトリ削除
NSFileManager* fileManager = [NSFileManager defaultManager];
NSString* storeDirectory = [self testStoreDirectory];
if ([fileManager fileExistsAtPath:storeDirectory]) {
NSError* error;
BOOL ret = [fileManager removeItemAtPath:storeDirectory error:&error];
GHAssertTrue(ret, @"remove save dir");
}
}
0 件のコメント:
コメントを投稿