看完上一篇的範例,是不是很簡單呢,一天馬上就學會了 TDD!
什麼?你說這樣一個小小的 function,你10秒就寫完了?幹嘛還要用 TDD,結果講了10分鐘。
上一篇利用範例來演示了一次 TDD,雖然說明了 TDD 的核心步驟,但為什麼要使用 TDD 這樣一個違反我們直覺的寫程式方式呢?
我整理了以下四個好處:
為了先寫出測試,開發者必須先去思考如何進行測試。
同時若嚴格實行 TDD,每個循環的步驟1~2都只編寫最少量的程式碼,程式們會趨向被編寫成小而獨立的區塊,而增加了維護性與再利用性。
因此會帶來幾個特點:
而如果開發的最後才寫測試,則容易發現函式之間互相依賴,導致難以編寫個別函式的單元測試。
所謂重構,指的是維持程式已完成的功能,但是整理程式碼以增加可維護性,像是把修改成更有意義的變數名稱、將過大的函式拆開等等。
利用 TDD 開發的過程中,幾乎所有的程式都維持在已編寫了單元測試的狀態,也許只要幾秒就能運行完一次所有的測試,這代表了一點,也是我認為最重要的一點。
==不怕把程式改到爆掉!==
==不怕把程式改到爆掉!==
==不怕把程式改到爆掉!==
當我們面對複雜又大量的程式碼時 (極端例子: 一個1000行的函式),會害怕我們一但修改了其中一行,導致整個程式崩潰,這時我們也跟著程式崩潰了,因為 Debug 地獄既煩人又耗時。
於是開發者會傾向不去觸碰以前寫好、目前運作上正常的程式碼,日積月累,最終演變成幾乎沒有可讀性。
但擁有測試就能夠一定程度確保,沒有把原本寫好的程式破壞掉,若有,測試通常會第一時間印出哪一行的單元測試有錯誤,這也是說 TDD 的每個循環都做了一次 regression test (回歸測試)。
讓開發者更勇於對程式碼進行重構,因此也容易保持簡潔。
相當多 Bug 會在執行測試時被檢測出來,Debug 的時間當然也減少了。
同時每一個函式小而獨立,要檢測出 Bug 出在哪一個函式也就相對容易。
覆蓋率是指,程式碼有被測試執行過的比例,測試的工具套件能夠提供。
這一點算是使用 TDD 開發附帶的好處,因為我們在開發的同時,一邊也在寫著測試,程式的測試覆蓋率會非常高,這會讓我們對自己寫出來的程式很有信心。
開發後一次編寫所有測試,較容易忽略一些可能發生的正常執行情況,另一方面一次花費大量的編寫時間也可能會讓開發者想偷懶。
雖然 TDD有這些好處,但在使用上也有它的前提,以及要注意的陷阱:
1. 一定要能夠執行自動化測試
2. 修改要能夠馬上執行
這樣才能讓每個 TDD 的循環很快地進行,這表示不少跟硬體相關的開發無法使用 TDD (像是嵌入式需要把程式燒錄到開發板上)。
3. 測試們同樣需要被維護
並不是寫了測試,程式就一定會保持整潔,有可能開發者怕測試壞掉,反而又避免去修改測試程式,那還是會造成沒有可讀性。
4. 並不是所有測試都通過了,就表示沒有 bug
寫過程式大概都知道,邏輯的錯誤不容易查,同時自動化測試也可能寫錯,甚至是原本就並未包含在需求內的,但在系統上線時卻發生。
看完了對於使用 TDD 的理由,下一篇讓我們繼續看更多的範例,一步步實踐 TDD 吧。