Unit Test 在使用 TDD 開發時,除了單元測試的角色之外
更像是需求的描述者
但回歸到真正的實務情境上,往往遇到的不是從無到有的開發
而是從既有的架構中去新增額外的功能
於此, Unit Test 更像是重構時的保險裝置
在練習的範例中,重構大略可以條列為下列步驟:
- 測試包覆:使用維度更大的測試包覆需要重構的部份
- 驅動測試:使 Visual Studio 可以驅動上述測試
- UI邏輯分離:加上註解,使用 DTO 技巧分離 UI 與邏輯
- 功能分拆:重新構築函式,將維度不同或重複的程式碼分離為子函式
- 主動詞分離:用物件導向的角度讓「主詞」「進行」某個動作
- 單元測試:對於第 6 點的動作撰寫 Unit Test
- 實作介面:讓第 5 點「主詞」的物件們實做同一個 Interface
- 蓋工廠:透過工廠依據不同條件產出「主詞」物件
重構是一個按部就班的過程,一次一個動作
每個步驟執行完畢之後,都跑一次測試,確保行為正確
就算沒有完成到最後一個步驟,它仍然是個可以正常使用的程式碼
不影響其功能,反應到開發流程中,這就是敏捷開發運行的基石
重構過程中切忌同時加入需求,一次僅做一件事,按部就班,穩紮穩打才是上策!
這個例子我一做了三次,有一種練拳的感覺
基本的套路練熟之後,當我實際運用在現實的複雜案例中
真的好像明白了什麼,打通了某些關節
真實的案例是要加上新需求時,必須進行某種程度的重構
當我想要加上高維度的 UI 測試,發現實在太費時,光是軟體啟動就要一兩分鐘
這完全不符合 Fast 的原則,就算能夠測試,也無法方便驗證每個重構步驟
破壞意圖導向的設計流程
於是我捨棄了這個層面的測試方式~
重新思考這個測試的意義與價值,與其驗證目的為何
目的是要確保我重構某個 function 時,其行為與原來相同的測試保護
所以我先謹慎小心的進行最小部份有把握的重構(抽離某些簡單的相依性)
然後對這個要重構的 function 設計不少單元測試,作為我的測試保護
接著運用上述範例練習的一些技巧,開始逐步的進行重構工程
每個重構步驟完成後,都執行一開始建立的單元測試驗證其正確性
確保重構過程無誤,當重構工程結束後,再行加入新的功能。
收工!
在重構過程中,遇過了幾次紅燈,實在令人興奮
自己架設的保護網好像起了作用,試想這樣的錯誤,若發行出去
何年何月才會被發現,被發現後要再花多少時間除蟲才能找到問題
有 Unit Test 保護的重構,真的會比較慢嗎?似乎不會喔~