ObjcUnit その6

2003/10/06


undoにだまされるな! その2

ずいぶんと空いてしまったので、すっかり忘却モードのundoです(^^;;
というわけで、今回はリハビリにはちょうどいい感じですね。


テストをちゃんと先に書こう その2

というわけで、もう一つテストしてないのはなんだか分かっていますよね?

  1. ほら、やっぱり、テストしてない!
    - (NSString *) description;
    
    やっぱ使う前にテストを書かないとね(^^;;
    というわけで、使う前までタイムスリップです。
  2. とにかく、テストを書こう
    というわけで、こんな感じのテストを書くわけね。
    - (void) testDescription
    {
    	SmallInteger* one = [SmallInteger initWithInt:1];
    	[self assert:[one description] equals:@"SmallInteger(1)"];
    }
    
  3. descriptionをFake Itしよう!
    まずはテストtestDescriptionを成功させるように、メソッドdescriptionをFake Itするわけですね。
    - (NSString *) description
    {
    	return @"SmallInteger(1)";
    }
    
  4. こんな実装じゃ、ダメじゃん!
    自分で実装しているんだから、テストは通っても、こんな実装じゃダメなのは、すぐに分かるよね。すると現状の実装の弱点も分かるわけね。「1以外は正しい文字列を取得できない」ってのは、すぐに分かるわけさ。それじゃテストを追加して、こんな感じだね。
    - (void) testDescription
    {
    	SmallInteger* one = [SmallInteger initWithInt:1];
    	SmallInteger* two = [SmallInteger initWithInt:2];
    	[self assert:[one description] equals:@"SmallInteger(1)"];
    	[self assert:[two description] equals:@"SmallInteger(2)"];
    }
    
  5. まじめに実装するべ!
    ここまでくると、ちゃんと実装しないとね。
    - (NSString *) description
    {
    	return [NSString stringWithFormat: @"SmallInteger(%d)", value];
    }
    
  6. いつになったら終わり?
    もし、まだ気になるところがあるんだったら、テストを追加していけばいいわけ。しかし、そうやっていくと、いつまで経っても終わらないよね?
    テストを追加したんだけど、テストに失敗しないことだってあるよね。こうなったら、このテストは要らないor重複しているかも?と考えましょう。そうしたら、ほとんど終わりです。たとえば、
    - (void) testDescription
    {
    	SmallInteger* one = [SmallInteger initWithInt:1];
    	SmallInteger* two = [SmallInteger initWithInt:2];
    	SmallInteger* five = [SmallInteger initWithInt:5];
    	[self assert:[one description] equals:@"SmallInteger(1)"];
    	[self assert:[two description] equals:@"SmallInteger(2)"];
    	[self assert:[five description] equals:@"SmallInteger(5)"];
    }
    
    なんていうテストを追加しても、おそらく無駄です。気休めにはなるけどね :-p

今日のおまけ

もっと詳しく知りたいぞ!という方は、JUnit 実践講座 - オブジェクトの文字列表現を活用しようがおすすめだよ。

ここで、「どうせなら0から9まで全部テスト書けばいいじゃん」って考えが出てきちゃう?
一般的なことを言えば、実装時間と実行時間の無駄です\(^O^)/

- (NSString *) description
{
	if (value == 1) {
		return @"SmallInteger(1)";
	} else if (value == 2) {
		return @"SmallInteger(2)";
	} else {
		return @"SmallInteger(5)";
	}
}
なんて、実装しても上のテストは通っちゃうんですよね。でも、そんな面倒な実装はかかないでしょ?
実装方法が分かっているから、ふつうの場合、2つテストすれば十分だってことも分かるんだよね。これがホワイトボックステストってわけさ。


戻る