iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 3
0
Software Development

如何一步步實踐TDD (測試驅動開發)系列 第 3

TDD 的理由

看完上一篇的範例,是不是很簡單呢,一天馬上就學會了 TDD!
什麼?你說這樣一個小小的 function,你10秒就寫完了?幹嘛還要用 TDD,結果講了10分鐘。

上一篇利用範例來演示了一次 TDD,雖然說明了 TDD 的核心步驟,但為什麼要使用 TDD 這樣一個違反我們直覺的寫程式方式呢?

我整理了以下四個好處:

1. 促使開發者思考結構

為了先寫出測試,開發者必須先去思考如何進行測試。

同時若嚴格實行 TDD,每個循環的步驟1~2都只編寫最少量的程式碼,程式們會趨向被編寫成小而獨立的區塊,而增加了維護性與再利用性。

因此會帶來幾個特點:

  • 寫出可重複測試的程式 (廢話)
  • 減少程式之間的耦合
  • 函式小而簡潔

而如果開發的最後才寫測試,則容易發現函式之間互相依賴,導致難以編寫個別函式的單元測試。

2. 易於重構 (Refactor)

所謂重構,指的是維持程式已完成的功能,但是整理程式碼以增加可維護性,像是把修改成更有意義的變數名稱、將過大的函式拆開等等。

利用 TDD 開發的過程中,幾乎所有的程式都維持在已編寫了單元測試的狀態,也許只要幾秒就能運行完一次所有的測試,這代表了一點,也是我認為最重要的一點。

==不怕把程式改到爆掉!==
==不怕把程式改到爆掉!==
==不怕把程式改到爆掉!==

當我們面對複雜又大量的程式碼時 (極端例子: 一個1000行的函式),會害怕我們一但修改了其中一行,導致整個程式崩潰,這時我們也跟著程式崩潰了,因為 Debug 地獄既煩人又耗時。

於是開發者會傾向不去觸碰以前寫好、目前運作上正常的程式碼,日積月累,最終演變成幾乎沒有可讀性。

但擁有測試就能夠一定程度確保,沒有把原本寫好的程式破壞掉,若有,測試通常會第一時間印出哪一行的單元測試有錯誤,這也是說 TDD 的每個循環都做了一次 regression test (回歸測試)。

讓開發者更勇於對程式碼進行重構,因此也容易保持簡潔。

3. 減少 Debug 的時間

相當多 Bug 會在執行測試時被檢測出來,Debug 的時間當然也減少了。

同時每一個函式小而獨立,要檢測出 Bug 出在哪一個函式也就相對容易。

4. 高測試覆蓋率

覆蓋率是指,程式碼有被測試執行過的比例,測試的工具套件能夠提供。

這一點算是使用 TDD 開發附帶的好處,因為我們在開發的同時,一邊也在寫著測試,程式的測試覆蓋率會非常高,這會讓我們對自己寫出來的程式很有信心。

開發後一次編寫所有測試,較容易忽略一些可能發生的正常執行情況,另一方面一次花費大量的編寫時間也可能會讓開發者想偷懶。


但 TDD 也不是萬靈丹

雖然 TDD有這些好處,但在使用上也有它的前提,以及要注意的陷阱:

1. 一定要能夠執行自動化測試
2. 修改要能夠馬上執行

這樣才能讓每個 TDD 的循環很快地進行,這表示不少跟硬體相關的開發無法使用 TDD (像是嵌入式需要把程式燒錄到開發板上)。

3. 測試們同樣需要被維護

並不是寫了測試,程式就一定會保持整潔,有可能開發者怕測試壞掉,反而又避免去修改測試程式,那還是會造成沒有可讀性。

4. 並不是所有測試都通過了,就表示沒有 bug

寫過程式大概都知道,邏輯的錯誤不容易查,同時自動化測試也可能寫錯,甚至是原本就並未包含在需求內的,但在系統上線時卻發生。


看完了對於使用 TDD 的理由,下一篇讓我們繼續看更多的範例,一步步實踐 TDD 吧。


參考資料


上一篇
TDD 範例一:函式 (PHP)
下一篇
TDD 範例二:物件 (PHP)
系列文
如何一步步實踐TDD (測試驅動開發)30

尚未有邦友留言

立即登入留言