單元測試法則

單元測試法則

What should we test?


Incoming & Outgoing Messages

上圖表示一個物件是如何被測試的。
測試物件的時候,你可以發現受測物件會接收發送訊息:
  • Incoming Messages 表示呼叫受測物件的訊息
  • Outgoing Messages 表示受測物件傳遞給其依賴物件的訊息
訊息可以被傳進物件,也會被物件傳遞出去(如上圖你可以看見有訊息進入物件,也有訊息從物件出去)。
進行測試時,你只能對物件傳遞訊息,沒有辦法看見物件的內部。這就是為什麼要
測試介面,不要測試實作。 (testing the interface, and NOT the implementation.)

測試介面讓我們可以隨意切換實作類別,並且不破壞測試程式。


Query & Command Messages

除了 Incoming & Outgoing Messages 以外,訊息還分為 Query 與 Command 兩種:
Query Message: messages return data without changing anything.
  • 只返回 Data,不做修改任何物件屬性的訊息
  • 不會替應用程式帶來副作用。
Command Message: messages modify data without returning any data.
  • 只修改物件屬性,但不返回任何 Data 訊息
  • 一定會有副作用。
合併的 Command 與 Query 訊息:
這種訊息除了修改資料與回傳資料外,還可能有隱藏的副作用。
(如新增一筆 user 資料並返回新的 user ID,但是 DB 內的 ID 自動 +1)
在商業邏輯一定要使用合併訊息時,一定要確保這些訊息不能含有意料外的副作用。

Test Double


為什麼要 Test Double?

1. 隔離依賴:

單元測試目的是要測試受測物件的行為是否符合預期,如果連受測物件的依賴物件也一起進行測試,那就叫做整合測試了。
因此單元測試需要隔離依賴。

2. 要求快速:

單元測試的時間應該非常短,才可以向開發者快速反饋信息

進行重構時,一點點修改就要立刻執行測試,確保功能沒有被改壞。如果每次執行測試,受測物件將訊息遞給依賴物件處理 15 秒才回傳值。就會大幅減緩開發速度。
使用測試替身隔離依賴物件,避免訊息在 N 多個物件之間來回傳遞。(參考上圖)即可加快單元測試的速度。
測試替身用途
Stub 用來測試 Outgoing Query Message

Stub 代替的訊息不會對整個應用程式帶來副作用,所以訊息如何被傳遞並不那麼重要。
Mock 用來測試 Outgoing Command Message


Mock 代替的訊息會對應用程式有副作用。所以一定要用 Mock 確保受測程式有沒有正確將訊息傳遞出去。

參考資源

留言

這個網誌中的熱門文章

Git Commit Message 這樣寫會更好,替專案引入規範與範例

Gitlab 合併請求 Merge Request 是什麼?

PHP OO 物件導向基礎教學