TDD道場の自分なりの補足
わんくま名古屋#11で昼にTDD道場をやりましたが、その際に気になった事などに関していくつか追記しておきます。
課題:FizzBuzz問題
プレイヤーは円状に座る。最初のプレイヤーは「1」と数字を発言する。次のプレイヤーは直前のプレイヤーの次の数字を発言していく。ただし、3で割り切れる場合は 「Fizz」(Bizz Buzz の場合は 「Bizz」)、5で割り切れる場合は 「Buzz」、両者で割り切れる場合は 「Fizz Buzz」 (Bizz Buzz の場合は 「Bizz Buzz」)を数の代わりに発言しなければならない。
http://ja.wikipedia.org/wiki/Fizz_Buzz
解き方:FizzBuzzというクラスを作成、say(int)というメソッドを作成する。
このsayメソッドは引数に対応する文字列を返す。
FizzBuzzってインスタンス化する必要はあるの?
どうでしょう?(答えになっていない)
メソッドが文字列を返し、テストが容易であるなら、もしかするとstaticメソッドで十分かも知れません。
しかし、今後の仕様変更による複雑化が見込めるのであれば、インスタンス化する仕様にしておくべきでしょう。
@Beforeでインスタンスを纏めて使うのはダメではないか?
今回のケースでは、全てのインスタンスを作成する時に同じコンストラクタを使っていたので、それをリファクタリングしました。
TDDではテストそのもののリファクタリングは重要だと考えています。
よって、テストを行う直前の「インスタンスの生成」部分を@Beforeによってまとめる形にリファクタリングするのは、決して間違っていないと思います。
JUnitでは、@Beforeアノテーションが付いているメソッドは、@Testメソッドの直前(すなわち、テストケース毎)に一度呼び出され、確実にインスタンスがクリアされます。
そのため、今回のケースではこの部分のリファクタリングを行いました。
なお、テストのリファクタリングに関しては、先にid:bleis-tiftが書いたのと同様の意見なので、以下に引用します。
テストコードの外部から見た振る舞いとはなんでしょうか?
大ざっぱに言うと、テストが成功するか失敗するか、でいいと思います。
テストコードのリファクタリングを「テストがすべて通っているときのみ行っていい」という制限を付けると、テストコードを変更してもどのテストも失敗しない状態が保たれればいいということになるでしょう*1。
http://d.hatena.ne.jp/bleis-tift/20100207/1265537875
なお、実際にコードを書いたときには、「全てGREENを確認」→「テストコードをリファクタリング」→「再び全てがGREENの事を確認」という流れで処理を行っていました。
一部のテストだけするべき?
TDDのテストはファストテスト(早いテスト)であるべきです。
そのテストが数百数千程度なら一瞬で終わらなければむしろまずいでしょ? というのと、一々テストを選択して実行するのが面倒なので、全てテストした方がいいと考えてます。
詳しくはレガシーコード改善ガイドをどうぞ。
レガシーコード改善ガイド (Object Oriented SELECTION)
- 作者: マイケル・C・フェザーズ,ウルシステムズ株式会社,平澤章,越智典子,稲葉信之,田村友彦,小堀真義
- 出版社/メーカー: 翔泳社
- 発売日: 2009/07/14
- メディア: 大型本
- 購入: 45人 クリック: 673回
- この商品を含むブログ (157件) を見る
テストの網羅性云々(ustコメント)
TDDのテストは技術者のためのテストであり、明確に品質を保証するためのテストではありません。
網羅性云々は別のテストを組む形で実装すべきであり、TDDのテストとは切り離して考えるべきです。
とりあえずここまで。