(iOS)Objective-C で Unit Test を書くには <a href="http://gabriel.github.com/gh-unit/">GHUnitと</a> いうテスト用ライブラリがあったりするみたい。
今回は、標準でついている SenTestingKit をつかってテストを書いてみたいと思います。
既存プロジェクト「Pokemon」にテストを追加していきます。
メニューの 「File」 → 「New」 → 「New Target...」 を選び、iOS の中にある Cocoa Touch Unit Testing Bundle を選択します。
Product Name は適当に UnitTest とか入力して、Project は Pokemon を選択します。 そうするとプロジェクト以下に、UnitTestディレクトリと、Productsディレクトリ以下に UnitTest.octest ができます。
メニューの 「Product」 → 「Edit Scheme」 を選び、Testタブの中にある Tests リストに UnitTest を追加します。
これでとりあえずテストは実行できるので、左上にある runアイコンをクリック長押しすると Test が選べるので、Test を選んで実行してみましょう。
きっと 「Unit tests are not implemented yet in UnitTest」 というエラーが出るはずです。 これは、UITest.m の testExample中の STFail 関数が動作するためです。 iOS SDK のドキュメントをみると、STFail は引数をエラーメッセージにして、テストを失敗させるようです。
[c] - (void) testExample { STFail(@"Unit tests are not implemented yet in UnitTest"); } [/c]
Unit-Test Result Macro Reference
特に必要ないコードなので、STFail の行はコメントアウトしておきます。 これでエラーなく実行できるはずです。
ここまでできたら、独自のテストを追加していきます。 UnitTestディレクトリを右クリックして、「New File」 を選び、iOS の中にある Objective-C test case class を選択します。 ファイル名を入力して、Add to targets に UnitTest を選択します。 ※ファイル名は、テストしたいクラスとか関数とかを接頭語にして、○○Test などにすると良いと思います。 ※今回は、加算、減算を提供する Calcクラスをテストするつもりで、CalcTest という名前にしました。
Calcクラスのコード [c] /* * calc.h /
import
@interface Calc : NSObject { } - (int)add:(int)x intY:(int)y; - (int)sub:(int)x intY:(int)y; @end
/* * calc.m /
import "Calc.h"
@implementation Calc : NSObject
(int)add:(int)x intY:(int)y { return (x + y); }
(int)sub:(int)x intY:(int)y { return (x - y); } @end [/c]
ファイル名を入力すると UnitTestディレクトリ以下に CalcTest.m と CalcTest.h ができますね。 このようにテスト対象のモジュールごとにテストファイルを生成するようになります。
では、生成されたファイルをいじっていきます。 まずは、CalchTest.h で テスト対象になるファイルを import して、テストのための関数を宣言します。 ついでに必要のない testAppDelegate と testMath の定義を削除します。
[c]
define USE_APPLICATION_UNIT_TEST 1
import
import
import "Calc.h" // 追加
@interface CalcTest : SenTestCase { Calc *calc; }
if USE_APPLICATION_UNIT_TEST
- (void)testCalcAdd; // 追加
- (void)testCalcSub; // 追加
else
endif
@end [/c]
Calc.h の読み込みと、テスト用の関数を追加しました。 関数は test○○ という感じで、接頭語を test にする必要があります。
次は CalcTest.m にテストコードを書いていきます。 こちらでも、必要のない testAppDelegate と testMath の定義を削除します。
[c]
import "CalcTest.h"
@implementation CalcTest
(void)setUp { calc = [[Calc alloc] init]; }
(void)tearDown { [calc release]; }
if USE_APPLICATION_UNIT_TEST
(void)testCalcAdd { int x = 1, y = 2; STAssertEquals(3, [calc add:x intY:y], @"Calc::add success"); }
(void)testCalcSub { int x = 1, y = 2; STAssertEquals(-1, [calc sub:x intY:y], @"Calc::sub success"); }
else
endif
@end [/c]
setUp関数はテスト開始時に自動で呼び出されます。 この中で、calc を初期化します。
tearDown関数はテスト終了時に自動で呼び出されます。 この中で、calc のメモリ領域を解放します。
test○○ の中では STAssertEquals関数で第1引数と第2匹数の値が同じかをテストしています。 ※今回は add、sub の結果が正しいかどうかだけテストしてます。
最後に、テスト対象になる Calcクラスのファイルをビルドターゲットに追加します。 プロジェクトのアイコン(?)を選び、TARGETS の UnitTest で Build Phasesタブの Compile Spirces に Calc.m を追加、Copy Bundle Resoueces に Calc.h を追加します。
これで実行すると、成功時は特に何も表示させずに終了し、エラーがあればエラーが表示させて終了します。 一応 Debug Console に詳細出てますが、ちょっとわかりにくいですね。。。
なにはともあれ、こんな感じで Unit Test 書くことができます。 おわり。