前言
測試驅動開發是這樣一件事
1. 在寫任何產品程式碼前,先寫測試程式
2. 由於還沒有寫任何程式,所以通不過測試 ===> 紅
3. 使用任何手段,寫下通過測試的程式碼 ===> 綠
4. 使用任何你所知道的軟體工程手法重構程式碼 ===> 重構
TDD第一定律
我們相信撰寫測試程式所花掉的時間,會在後面除錯階段賺回來
TDD第二定律
我們相信TDD可以使我們得到更好的程式架構
TDD成長階段
1. 先寫測試,再寫程式
這種事完全是天方夜譚
打死不信
2. 半信半疑,但開始嘗試在專案中使用
3. 更進一步了解TDD所帶來的好處
為自己的思考充滿漏洞而感到不可思議
4. 沒TDD會死
開始懷疑並攻擊所有沒使用TDD的人
對沒使用TDD寫的程式碼完全沒信心
5. 行於所當行,止於所不得不止
何時該TDD,何時該放手去做
在專案品質,預算,時間達成完美平衡
探索未知事務
一種探索真相的方法
1. 假設某程式碼可通過一系列的測試集合 T = { test_1 , test_2, test_3 ... test_n }
2. 通過 t(n+1) 組測試的程式碼
應該比
通過 t(n)測試的程式碼更為可信
3. 同理可以通過 t(n) 組的程式碼比可以通過 t(n-1) 組的更為可信
4. 測試程式若經過精心設計
那麼我們可以使用一組合理數目的測試程式來"定位"出正確的程式碼
5. TDD是藉由寫測試程式來讓電腦告訴我們方向
一個簡單的範例
費伯納西數列
第一輪 (紅)
乖小孩要先寫測試程式
AssertTrue( f(1) == 1 );
還沒寫下任何程式碼,當然不會過關 ====> 紅
第二輪 (綠)
撰寫通過測試的程式碼,無論手段多卑鄙 (顯式實現法)
int f(int n)
{
return 1;
}
卑鄙無恥,過關 ===> 綠
第三輪 (紅)
增加測試程式以拆穿和平的假象 (三角定位法)
AssertTrue( f(1)==1 );
AssertTrue( f(2)==1 );
AssertTrue( f(3)==2 );//測試不過 ===> 紅
正義終會戰勝邪惡
第四輪 (綠)
撰寫通過測試的程式碼,無論手段多卑鄙
int f(int n)
{
if( n == 3 )
return 2;
else
return 1;
}
卑鄙無恥,過關 ===> 綠
第五輪 (重構)
老師說魔術數字是不好的,所以我們重構程式碼
2 是什麼, 1 + 1 = 2
1 是什麼, f(1)=1 , f(2)=1
int f(int n)
{
if( n == 3 )
return f(1)+f(2);
else
return 1;
}
程式架構獲得改善
第六輪 (紅)
增加測試程式來伸張正義 (三角定位法)
AssertTrue( f(1)==1 );
AssertTrue( f(2)==1 );
AssertTrue( f(3)==2 );
AssertTrue( f(4)==3 );//測試不過 ===> 紅
第七輪 (綠)
某硬體工程師說寫程式就是if else
int f(int n)
{
if( n == 4 )
return 3;
else if( n==3 )
return f(1)+f(2);
else
return 1;
}
無能但可用 ===> 綠
第八輪 (重構)
前述程式碼有辱斯文,所以重構美化之
3 是什麼 2 + 1 =3
2 是什麼 f(3) = 2
1 是什麼 f(2) = 1
int f(int n)
{
if( n == 4 )
return f(2)+f(3);
else if( n==3 )
return f(1)+f(2);
else
return 1;
}
第九輪 (重構)
老師說重複的程式碼是不好的
所以我們合併條件式
int f(int n)
{
if( n >= 3 )
return f(n-2)+f(n-1);
else
return 1;
}
於是我們使用測試驅動開發得到費伯納西數列
TDD缺點
1.TDD Happy( 與之相對的有Pattern Happy )
誤以為TDD可以解決所有編程問題
除非恰巧你有無限時間和預算2.架構複雜化
在TDD過程中會引入過多不必要中介層
俗話說殺雞用牛刀
違反TDD第一和第二定律3.會失去整體視野
思維集中在 => 紅-綠-重購
只能取得局部戰勝利
但軟體是一個整體,取得所有局部戰勝利,不代表軟體可用
TDD的攻擊
1. 局部戰勝利不等總體戰
沒錯,但沒有局部勝利,就不會有總體勝利
在正正當當做生意的情況下
有好軟體的品質是成功事業的一環當然確實有王牌業務,擅長把垃圾當黃金賣
2. 容易引入複雜架構而過度設計
人非聖賢,孰能無過
大家都是在失敗中學習成長
不使用TDD,就不會引入複雜設計嗎?3. 寫測試很花時間
TDD是藉由寫測試程式讓電腦告訴我們錯了
錯誤越晚修正,修正成本越高當然資深的架構師,由於在舊專案的失敗經驗
在新專案可以直接進入通靈狀態
結論
TDD是碼農邁向更好碼農的必修課程
斷不需因為它的缺點而停止學習和使用它
我們不能因為怕小孩會把玩具弄亂,而把玩具收起來問: 碼農中的霸主是什麼?
答: 還是碼農祝天下的碼農,能在工作中取得樂趣