業界很多朋友知道我有在做單元測試,常問我:要選NUnit好?還是用Visual Studio內建的單元測試好?
這邊針對我的一些使用經驗,簡單的介紹一下測試相關工具的差異。
[如何提升系統品質]系列文章連結
NUnit好,還是VS內建的單元測試工具好?
我之前的單元測試撰寫經驗,都是使用NUnit,原因很簡單:免費。 免費的重點在於,其他的工具對它的整合程度會比較高。
這邊所謂的其他工具,最重要的就是CI server。
有很多的CI server也都是免費的,對這些open source的工具來說,NUnit是一個輕巧簡便,該有的都有的單元測試工具。
但,假設不管單元測試以外的相容性部分,我得說VS內建的單元測試大勝!
單元測試導入難在哪?難在很多步,第一步最難的就是dev的心理障礙。
dev的心聲:
1.測試程式?為什麼我寫code都沒時間了,還要我寫測試程式?
2.針對一個功能寫一份production code就夠吃緊了,還要寫好幾份測試程式來測這一份code?
3.程式碼一改,需求一改,原本只要改一份production code,現在要改1+N份程式?
4.測試程式有寫跟沒寫一樣,為什麼我還要新增一個專案,手刻一個測試的class,測試的方法,還要寫相關的輸入、驗證相關的輸出?每次都刻這個真的很浪費時間。
是的,單元測試導入最難的第一步,就是工程師覺得寫測試程式不夠方便、快速,是額外的負擔。
Visual Studio的單元測試可以為我們做到什麼
1.自動產生測試程式相關框架
在Visual Studio裡面,建立測試專案、建立測試類別、建立測試方法、建立測試目標初始化、測試方法參數初始化、驗證的語法,都是自動產生的。其中還包括了,該測試類別每次初始化與結束要進行的方法,測試方法執行前後要進行的方法,也都自動產生好了。
NUnit也有相關自動產生測試程式的工具,例如NUnit Test Generator,也是要錢。或是免費,但沒持續升級的工具:NUnit Test Case Code Generator
2.提供Data-Driven Test
在VS的單元測試中,可以透過精靈去設定該方法需要哪些測試案例,在同一個方法中,測試每一個input, output是否符合原本的預期。
3.與開發工具IDE的整合
例如執行測試的熱鍵,雖然說這不是每個人都需要,而且也可以自己設定,但在開發過程中,Unit Test的程式碼跟Production code其實是一體兩面的。都要可以建置成功,都要可以被測試成功。寫出的每一個功能都應該要能符合預期。
在code coverage的整合上,VS內建的程式碼涵蓋率,還是比R#(要錢)跟NCover(要錢)的整合好多了。Code Coverage的工具一樣都要錢,VS的工具則可以跟開發的程式順利的整合在一起。
偵錯上,也可以把測試程式就當作production code一樣來偵錯,相當方便。
NUnit則需額外透過其他套件來執行,例如TestDriven.NET(要錢)與Visual Nunit。
簡單的說,你需要用到的,基本上VS內建的都有。而NUnit就像一個內聚力很高且功能良好的單一單純的單元測試工具,需要更多其他的工具輔助,才能擁有多面向的綜效。
4.Class Accessor的產生
個人認為,這一點跟自動產生的效益是最高的。VS內建的單元測試,打破了一般單元測試的基本原理,也就是只能測試類別公開出來的部分。在VS的單元測試裡,只需要滑鼠右鍵,產生單元測試,連所有的private, protected, internal, public都可以測試。這時候VS會幫你產生一個Accessor的class(類似proxy的概念),並將其所有屬性、方法、事件等非公開的部分,public出來協助進行測試。
如果沒有這樣的方式,原本的測試方式只能:
(1)在設計production code時,為了測試方便,將其public給外界。但這樣帶來的後果,我個人認為得不償失。無論如何,都不該因為『for 測試方便』而修改production code,且導致production code在visibility上品質是下降的。
(2)透過其他public的方法,來黑箱測試非public的部分。也就是外部只care類別public的部分,因為外部也只能用public的部分。這雖合理,但單元測試想要測試的方法,若是黑箱測試,則失去最大效益。
5.不只Library可以測試
Web Application, Website, Console(SilverLight, WCF服務網站跟Winform我沒試過),也都可以直接透過一樣的方式,產生測試專案、測試方法。
這真是一大福音,如果為了要做測試,而進行大幅架構型的重構,才能進行測試。那再重構之前就需冒著production code被改壞的風險。但不重構,又無法讓程式具備可測試性。這時候透過VS內建的測試工具,可以幫我們產生對應的測試(其實應該歸類在整合測試),讓整個重構的cycle可以啟動,這也是NUnit不容易辦到的。
結論
NUnit與VS內建Test之爭,簡單的說就是open source工具的組裝,以及Total Solution的比較。
如果,你們已經使用相當多的open source工具,來做軟體工程與開發工法程序相關的infrastructure,且針對的對象,不只是.NET。那,我會建議使用NUnit。
如果,你們是使用TFS來做版本控管以及CI Server,那千萬不要捨棄VS內建的單元測試,這會讓你事半功好幾倍,如有神助一般。
如果,你們還在考量要使用哪一種,沒有其他包袱,又希望導入快速、成功,那我會建議使用TFS+Visual Studio。Total solution的問題點只有:
1.錢。
2.工具相依於MS。
而工具相依特點的另外一面卻也是優點,代表即使Visual Studio版本的migration, .net framework的migration, CI的migration,微軟都會以他們所支援的工具、技術為主要優先support。
Open source的缺點:
1.需要大量的survey與組合多個工具。且這裡的組合,基本上都脫不了寫code。如果不必寫code,恭喜你,肯定又有open source的IDE工具幫你做掉,如果好用,它肯定要收費。
2.當組合多個工具,一切盡善盡美時,相信微軟又將IDE開發工具、.net framework等等,往上提升了一個版本,這時候多個工具組合出來盡善盡美的聖戰士,就可能會面臨升級升不上去的窘境。
3.當你大刀闊斧的撩下去改open source的工具,以客製化因應你們系統上的需求時,open source的migration又補你一刀。屆時就會面臨:migration open source tool,可以支援較新的MS技術版本,但又得重新客製化一次。不migration,又無法以新的技術來開發新的系統。
Open Source大部分都是一些神人的休閒之作,他們懷著一顆懸壺濟世的心情來對這個世界貢獻,他們創造了許多的美好,推動了許多技術的演進,但他們也有家庭要顧,也有小孩爹娘老婆要養。所以很難在短時間內,馬上就跟上微軟技術的演進。而CI, Unit Test, 這種跟開發息息相關的infrastructure,卻很難因為open source的作者沒空migration而作罷。
這就是我建議的,如果錢夠,又沒包袱,Total Solution增加的購買成本,會相對的降低未來升級成本。且開發上的簡便、迅速,可以買到工程師的快樂,導入軟體工程的成功率也比較高,就看管理者的目光看多遠了。
其他的Reference
1.NUnit vs. MsTest: NUnit wins for Unit Testing.
2.NUNIT和VISUAL STIDIO的比較
3.MSTest vs. NUnit with Visual Studio 2010 & TDD