Jan 292012
 

Xcode4でCoreDataを使ってUnitTests(Logic)を行う場合の設定方法。新規プロジェクト生成でUnitTestsをする設定にチェックを入れた場合のDefaultはUnitTests(Application)となる。つまり、UnitTests(Logic)は開発者が新規設定が必要となる。

UnitTestsのタイプ

  • Application Test(UIViewなどを含めた全体テスト)
  • Logic Test(UI以外のデータのテスト)
アプリケーション(以下アプリ本体)のidentifierは(com.f60k.Hergo)という仮想アプリで説明する。

Logic Testの作成Howto

Testing Bundleを新規作成。Add Targetボタンを押すとダイアログが出現する。名前はアプリ本体の名前にLogicTestsを追記したものにした。指定したProductName(com.f60k.HergoLogicTests)は後で使うので覚えておく。追加されるとフォルダが作成される。

CoreDataの3つの重要ポイント(Logic Testの場合)

  • xcdatamodelはコンパイルに含める(モデルの設定)
  • NSBundleはidentifierから設定(モデルの設定)
  • NSStoreTypeはInMemoryに設定(永続ストアの設定)
xcdatamodelはコンパイルに含める
NSManagedObjectModelを作成するときには(.mom)ファイルが必要。コンパイルに含めた(.xcdatamodelファイル)から生成される。アプリ本体では自動的に追加されるが、Logic Testでは開発者が追加しなければならない。
NSBundleはidentifierから設定
開発マシンにはどこかに以下のように.momファイルが保存されている。これが実際のbundle(com.f60k.HergoLogicTests)の中身である。正しく生成され保存されているのがわかる。
bundleが存在するのは分かった。このbundleの位置(path)からmodelを取り出す。[NSBundle mainBundle]の指す位置はLogic Testでは取得できない。
mainBundleから取り出せたbundleのidentifierは
  • アプリ本体→com.f60k.Hergo
  • Application Test→com.f60k.Hergo
  • Logic Test→null(com.f60k.HergoLogicTestsとなれば問題ないが…)
Logic Testで正しく取り出すには以下のように開発者がハードコードで指定して取得する。(ハードコードの問題点は後半。)
[NSBundle bundleWithIdentifier:@"com.f60k.HergoLogicTests"];
 これによりidentifierが正しく特定され、bundleの保存されている場所(path)を探し出すことが出来る。
NSStoreTypeはInMemoryに設定
  • NSSQLiteStoreType
  • NSInMemoryStoreType

その他重要ポイント(Testに関係なく一般的に行うこと)

  • CoreDataのフレームワークをビルド設定に追加する
  • prefixヘッダにCoreDataを追加する
CoreDataのフレームワークをビルド設定に追加する
prefixヘッダにCoreDataを追加する
LogicTestsのSupporting Filesのpchファイルの中にCoreData.hを追記する。
#import <CoreData/CoreData.h>

Application TestではApplicationにターゲット依存しているため、通常のアプリ開発と同じ手順で問題ない。

ハードコードの問題点

Logic Testの設定をハードコードすると書き換えでミスをする可能性がある。自動で設定が切り替わるようにしておくと便利である。

自動切り替え設定のポイント

  • スキーマに環境変数を設定する
  • 環境変数の値を設定値の分岐に利用する
スキーマに環境変数を設定する
環境変数の値を設定値の分岐に利用する
getenv()を使って設定した変数を取り出せば、通常はSQLでLogic TestではInMemoryと使い分けが出来る。
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Hergo.sqlite"];
NSString *storeType = NSSQLiteStoreType;
#if DEBUG
if (getenv("logicTests"))
{
storeType = NSInMemoryStoreType;
storeURL = nil;
}
#endif
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:storeType configuration:nil URL:storeURL options:nil error:&error])
{

参考サイト
http://stackoverflow.com/questions/7274711/run-logic-tests-in-xcode-4-without-launching-the-simulator
http://iamleeg.blogspot.com/2010/01/unit-testing-core-data-driven-apps-fit.html

コメント

個のコメント

Powered by Facebook Comments

 Posted by at 22:51

  One Response to “CoreDataのUnitTest”

  1. NSBundle bundleWithIdentifier 指定すれば取れるんだ。 “CoreDataのUnitTest” http://t.co/vCjmAmRl6l

Sorry, the comment form is closed at this time.