TDD Fizz Buzz 20100122 biac TDD 1 1
TDD ってどんな感じ? Fizz. Buzz を作ってみる 2010/01/22 biac
TDD 開始: 1 ⇒ “ 1” が返る [Test. Method] public void Test. Say 1() { Fizz. Buzz. Player p = new Fizz. Buzz. Player(); Assert. Are. Equal<string>("1", p. Say(1)); } ⇒ コンパイルエラー! (RED) → 製品コードのソースファイル Fizz. Buzz. Player. cs を作る internal class Fizz. Buzz. Player { internal string Say(int number) { return "1"; } } "1" が返れば いいのよ~ !!
2 ⇒ “ 2” が返る [Test. Method] ※ テスト追加時には public void Test. Say 2() そのテストだけ実行 { Fizz. Buzz. Player p = new Fizz. Buzz. Player(); Assert. Are. Equal<string>("2", p. Say(2)); } ⇒ テスト失敗! (RED) → 2つのテストを同時に通すには? (三角測量) internal class Fizz. Buzz. Player { internal string Say(int number) { return "1"; //return "1"; return number. To. String(); } } ※ 製品コード修正時には 全てのテストを実施
ちょっとテストをリファクタ private Fizz. Buzz. Player _test. Target; 安全索が無いので 慎重に! [Test. Initialize] public void Test. Initialize() { this. _test. Target = new Fizz. Buzz. Player(); } [Test. Method] コンストラクタは 1つだけ。 public void Test. Say 1() { [Test. Method] Fizz. Buzz. Player p = new Fizz. Buzz. Player(); 将来、増えることも無さそう。 public void Test. Say 1() { Assert. Are. Equal<string>("1", this. _test. Target. Say(1)); } } [Test. Method] public void Test. Say 2() { public void Test. Say 2() Fizz. Buzz. Player p = new { Fizz. Buzz. Player(); Assert. Are. Equal<string>("2", this. _test. Target. Say(2)); }
3 ⇒ “Fizz” が返る [Test. Method] public void Test. Say 3 Fizz() { Assert. Are. Equal<string>("Fizz", this. _test. Target. Say(3)); } internal class Fizz. Buzz. Player { internal string Say(int number) { if (number == 3) return "Fizz"; return number. To. String(); } } 3 だったら "Fizz" を返せ ばいいのよ~ !!
5 ⇒ “Buzz” が返る [Test. Method] public void Test. Say 5 Buzz() { Assert. Are. Equal<string>("Buzz", this. _test. Target. Say(5)); } internal class Fizz. Buzz. Player { internal string Say(int number) { if (number == 3) return "Fizz"; if (number == 5) return "Buzz"; return number. To. String(); } } 5 だったら "Buzz" を返 せばいいのよ~ !!
6 ⇒ “Fizz” が返る [Test. Method] public void Test. Say 6 Fizz() { Assert. Are. Equal<string>("Fizz", this. _test. Target. Say(6)); } internal class Fizz. Buzz. Player { internal string Say(int number) { //if (number == 3) 3 の倍数だったら "Fizz" if (number == % 33) == 0) return "Fizz"; ※ 三角測量 if (number == 5) return "Buzz"; return number. To. String(); } } もう分かってるけど、 テストを通すのに関係無 いから、こっちは我慢 !
10 ⇒ “Buzz” が返る [Test. Method] public void Test. Say 10 Buzz() { Assert. Are. Equal<string>("Buzz", this. _test. Target. Say(10)); } internal class Fizz. Buzz. Player { internal string Say(int number) { if (number % 3 == 0) return "Fizz"; //if (number == 5) if (number == % 55) == 0) return "Buzz"; return number. To. String(); } } 5 の倍数なら "Buzz" ※ 三角測量
15 ⇒ “Fizz Buzz” が返る [Test. Method] public void Test. Say 15 Fizz. Buzz() { Assert. Are. Equal<string>("Fizz Buzz", this. _test. Target. Say(15)); } internal class Fizz. Buzz. Player { internal string Say(int number) { if ((number % 3 == 0) && (number % 5 == 0)) return "Fizz Buzz"; if (number % 3 == 0) いきなり書いちゃったけど。難 return "Fizz"; if (number % 5 == 0) しいときは三角測量! return "Buzz"; return number. To. String(); } }
リファクタリング internal string Say(int number) { bool is. Multiple. Of 3 = (number % 3 == 0); bool is. Multiple. Of 5 = (number % 5 == 0); //if ((number % 3 == 0) && (number % 5 == 0)) if (is. Multiple. Of 3 ((number % 3 ==&& 0)is. Multiple. Of 5) && (number % 5 == 0)) return "Fizz Buzz"; //if (number % 3 == 0) if (is. Multiple. Of 3) (number % 3 == 0) return "Fizz"; //if (number % 5 == 0) if (is. Multiple. Of 5) (number % 5 == 0) return "Buzz"; return number. To. String(); } 重複を排除するため キャッシュ変数を導入
完成 ! • 最後にオールグリーンを確認して、 チェックイン! internal string Say(int number) { bool is. Multiple. Of 3 = (number % 3 == 0); bool is. Multiple. Of 5 = (number % 5 == 0); if (is. Multiple. Of 3 && is. Multiple. Of 5) return "Fizz Buzz"; if (is. Multiple. Of 3) return "Fizz"; if (is. Multiple. Of 5) return "Buzz"; } return number. To. String();
0 ⇒ 例外が出る [Test. Method] [Expected. Exception(typeof(Argument. Out. Of. Range. Exception))] public void Test. Say 0 Error() { string result = this. _test. Target. Say(0); Assert. Fail("例外が発生せず、'{0}'が返りました。", result); } internal string Say(int number) { if (number < 1) throw new Argument. Out. Of. Range. Exception("number", number, "Fizz. Buzz ゲームは 1 から始まります。"); bool is. Multiple. Of 3 = (number % 3 == 0); bool is. Multiple. Of 5 = (number % 5 == 0); if (is. Multiple. Of 3 && is. Multiple. Of 5) return "Fizz Buzz"; // …
- Slides: 26