TDD (Test-driven Development,測試驅動開發) 是一種開發技巧,透過在實作前先寫測試,幫助實作者更早的想清楚做一件事情想要達成的效果是什麼。
那麼,為什麼我們需要 TDD?
首先我們需要回答:為什麼我們需要測試?
在維護專案時,我們會遇到一些問題,而寫測試正好能幫助我們解決這些煩惱:
而透過引入 TDD 方法,我們可以獲得更多好處,包含:
TDD 方法的循環為:寫一個測試 → 盡快讓測試通過 → 重構出簡潔的設計。
假設我們想要寫一個用來執行加法的函式,接收兩個參數,並回傳兩者相加的結果,那麼我們可以透過以下步驟來實作:
我們在心裡假設一個 add
函式,它會回傳兩個參數相加的結果,那麼這個函式的測試應該會長這樣:
接著我們開始想,應該要如何實作 add
函式,讓這個測試盡快通過呢?
如果要讓測試盡快通過,最快的方法就是直接回傳一個和測試結果相同的值,這麼一來,這個測試就會直接通過,這時我們還不需要在 add
函式裡添加任何邏輯。
我們看到在上一個步驟中,我們讓 add
函式直接回傳了一個固定的值,這樣的實作顯然不符合邏輯,但我們要抑制直接將函式改為回傳 a + b
的衝動,這樣太不 TDD 了。
我們要如何使用更 TDD 的方法來達成我們心裡的期待?
這邊我們引入另一個 TDD 的概念:三角定位法,三角定位法是指在實作時,我們可以透過多個測試情境來驗證我們的程式碼是否正確。
三角定位的來源是一個數學原理,當我們有兩個探測器時,就可以確定目標物體的位置,這個概念就很像我們寫多個測試情境驗證程式碼是否真的可用。
例如對於 add
函式,我們可以再寫一個測試情境:
這麼一來,原本的 add
函式因為永遠都會回傳 3,所以它注定失敗,這時我們就可以開始思考如何重寫 add
函式,讓這兩個測試情境都通過。
身為軟體工程師,應該不會容忍這麼醜的程式碼,這時我們可以利用 TDD 提出的另外一種方法繼續重構程式碼:消除重複。
重複其實就存在在測試和實作中,在測試情境中我們寫死了 1 和 2 作為參數,而在實作中我們也寫死了這兩個參數的結果,因此這樣的重複是可以被消除的。
透過把 add
函式的程式碼修改成這樣,我們就不需要寫兩次 1 和 2 了,這樣就算是消除了重複,至此我們就完成了 TDD 的整個循環。
回顧 TDD 的循環,你或許會質疑:這樣的寫法真的有必要嗎?不過就是一個簡單的加法函式,為什麼要大費周章把每一步切的這麼細?我大可以在寫完測試後直接實作相加的邏輯,或是根本不用寫測試,因為這個函式的功能實在太簡單了!
這樣的想法其實很常見,在這麼簡單的例子裡,採取這麼細碎的步驟或許沒有必要,但是 TDD 是一種思考模式,我們需要準備好這樣思考,以讓我們面對更複雜的功能。
在接下來的文章裡,我會介紹更多 TDD 的觀念和應用,相信我,在面對複雜情況時,TDD 會是你最好的朋友。