[單元測試]沒封裝成DLL也可以撰寫單元測試
前言
以單元測試的基本原理,就是透過一個測試專案,參考我們的目標Library封裝好的dll,接著撰寫Unit Test code,初始化我們的測試目標,invoke欲測試的方法,並驗證實際回傳值與期望值是否吻合。
但是,有很多時候,想要進行測試的對象,並不是切割得很乾淨的Library,而是個Console project或WebSite。要重構將其依照layer的概念,獨立到Library,可能是一件大工程。而這樣重構的大工程,又需要測試程式的保護。但不是Library,又無法引用測試,就形成一個互卡的局面。
免驚!Visual Studio支援的測試功能已經cover掉這一塊了。(這也是後來捨棄NUnit等test framework的主要原因)
Visual Studio支援可以直接對WebSite或Console Project中的class建立單元測試,只有這樣嗎?No, no, no!不只這樣,還支援了對非public的方法進行測試(就是這麼神奇)。如此一來,我們就不需要為了可測試性,將不需要public的方法公開,也不像之前只能透過黑箱跟code coverage來確定private method的正確性。我們可以針對private method,透過mock來驗證程式的邏輯。
需求說明
我們的Console Project裡面,已經有一個Convert的class,提供了一個得到民國年的方法。然而在一次survey的過程中,發現.Net其實有提供TaiwanCalendar的class供使用。我們想將原本愚笨的西元年-1911,重構成使用TaiwanCalendar的方式。但,我們要怎麼證明,修改前後結果一致?
設計步驟
Step1:
先針對我們已存在的方法,建立單元測試:
接著我們來撰寫我們的單元測試:
測試結果:
Step2:
重構我們的實際程式,將其改為使用TaiwanCalendar。
執行測試程式,一樣得到成功的結果。
重構前建立單元測試,重構後確定測試結果如同預期,重構完成!
結論
當我們可能因為bug/需求異動/功能增加/效能改善/增加可維護性,而需要對既有程式進行修改時,即使目標類別並未封裝成類別庫時,我們仍可以對其建立測試程式。透過測試程式的test case,通常是具代表性或最主要的input,來增加code coverage,確保每一行(或大部分的程式碼)都有被cover到,接著我們重構才能放心,才能確保重構後的結果與重構前相同。
當每次的bug發生,每次的重構進行,我們都為其建立單元測試程式,雖然表面上看起來要多花成本建立測試程式,但這些測試程式卻會逐漸的累積起來,成為系統品質的最佳保障。錯過一次,就可以擔保不會錯第二次。修改後,也可以保證不會影響到其他程式,至少可以保證,不會讓之前發生的錯誤,因為這次的修改而又再發生一次。
後記:其實Console project產生出來的exe檔,也是Assembly的一種,我這邊的舉例不好,應該至少要舉個測試private method的例子,才能顯示出VisualStudio自動產生Class Accessor的強大之處,容許我在之後再補文吧。
blog 與課程更新內容,請前往新站位置:http://tdd.best/