iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 7
0
Software Development

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

插入曲:關於 Interface 與 public / private

開始寫這個系列之後,討論到一個 TDD 使用時的議題,以及另一個相關的延伸問題,因此來聊聊我目前的看法。

1. TDD 與 定物件的介面 (Interface) 的先後?

物件導向 - 封裝

如果對物件導向有概念,會瞭解封裝的特性讓我們使用物件時,只要知道如何使用 public method / function 即可,也就是物件對外的 「介面」 Interface,而不需要瞭解其細節的實作,讓呼叫方面也使實作細節可以容易被改進。

比如說範例二PaymentListcalculate_sum()函式,讓使用 PaymentList 的人只呼叫 calculate_sum 這個介面,實際上是透過什麼公式加總那是實作細節,之後容易就能修改這細節 (e.g. 改成加權的計算)。

因此先定出一個物件的 Interface,會幫助釐清物件架構與開發。

但問題來了,使用 TDD 的要求是先寫測試,那麼定 Interface 算不算是在寫產品程式呢?

如果要定 Interface 的話,應該要在寫測試前,還是測試後?

TDD 的角度

先說結論,我目前認為這個問題的答案是 「都可以」,並不是對錯之分。

寫物件的 Interface 嚴格來說是在寫程式沒錯,然而 Interface 的實作細節終究是空的,只是在定義輸入輸出而已,那麼先定出 Interface 並不會造成問題。

而反過來,完全依循 TDD 的作法,從單元測試開始寫,一定也會在測試中呼叫這個函式,「呼叫」 就也已經包含了定 Interface 這件事,明確指出要傳入的參數(若有的話)、以及判斷預期的輸出或執行結果。

因此不管是先定 Interface,還是直接先寫測試,兩者都會達到定 Interface 的效果,也都不違反 TDD 的原則。


2. 要不要寫 private 函式的單元測試?

第二個議題思考的點,是關於要寫多少單元測試。

前面提到,物件 public 的函式代表了對外的 Interface,為了確認函式如預期地執行,所以我們寫 public 函式的單元測試。

那為了減少函式相依與提高測試覆蓋率 (程式碼有被測試執行的比例),所以對於 private / protected 的函式我們也該寫獨立的單元測試,如果這樣推論就有點問題了!

private 的函式們是簡化同一物件內重複的程式碼,雖然也可能被其他 private 呼叫,但最終還是會追溯到因為物件外對 public (interface) 的觸發

即使只有對 public 這些所謂物件外觀行為的函式寫單元測試,依舊會執行到全部 private,如果有沒被執行到的,那也就表示他們並沒有在任何地方被呼叫,成為永遠不會被執行的程式碼。

如果 private 函式有多種可能的輸入要被單獨測試,那也可能只代表,應該要將那個做了多種行為的函式,切分成多個小而獨立的函式。

所以只要考慮對所有 public 函式,而不要對 private 獨立進行測試。


參考資料


上一篇
TDD 範例三:用 PHPUnit 改寫範例二
下一篇
自動化測試的層級
系列文
如何一步步實踐TDD (測試驅動開發)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言