(iOS)Objective-CでUnitTest

            (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 書くことができます。 おわり。