單元測試和測試驅動開發的一些常見問題總結

此文收集一些平時使用單元測試碰到的問題和解決辦法,供你們參考。html

如何檢查返回的集合類是否符合指望?

Microsoft UnitTestFramework 若是須要元素的順序一致,可使用CollectionAssert.AreEqual;若是不須要考慮順序,可使用CollectionAssert.AreEquivalent。(有的地方說MSTest的Assert.AreEqual支持集合類型比較,我測試過,忽悠人的
nUnit 同上
xUnit xUnit的Assert.Equal(c1, c2)能夠支持集合類型比較,c1和c2的元素順序必須一致

Microsoft UnitTestFramework / nUnit / xUnit 比較,使用哪一個框架更合適?

Microsoft UnitTestFramework和nUnit的用法很是相似,而xUnit因爲吸收了nUnit的設計上的經驗,用法更加簡潔。下面是周公寫的兩篇文章,nUnit和xUnit介紹的很是詳細,你們能夠閱讀一下:git

什麼是Mock?

單元測試的目標是一次只驗證一個方法,小步的前進,細粒度的測試,可是假如某個方法依賴於其餘一些難以操控的東東,好比說網絡鏈接、數據庫鏈接、系統時間、或者是Servlet容器,那麼咱們該怎麼辦呢?要是你的測試依賴於系統的其餘部分,甚至是系統的多個其餘部分呢?在這種狀況下,假若不當心,你最終可能會發現本身幾乎初始化了系統的每一個組件,而這只是爲了給一個測試創造足夠的運行環境讓它們能夠運行起來。忙乎了大半天,看上去咱們好像有點違背了測試的初衷了。這樣不只僅消耗時間,還給測試過程引入了大量的耦合因素,好比說,可能有人興致沖沖地改變了一個接口或者數據庫的一張表,忽然,你那卑微的單元測試的神祕的掛掉了。在這種狀況發生幾回以後,即便是最有耐心的開發者也會泄氣,甚至最終放棄全部的測試,那樣的話後果就不能想像了。github

再讓咱們看一個更加具體的狀況:在實際的面向對象軟件設計中,咱們常常會碰到這樣的狀況,咱們在對現實對象進行構建以後,對象之間是經過一系列的接口來實現。這在面向對象設計裏是最天然不過的事情了,可是隨着軟件測試需求的發展,這會產生一些小問題。舉個例子,用戶A如今拿到一個用戶B提供的接口,他根據這個接口實現了本身的需求,可是用戶A編譯本身的代碼後,想簡單模擬測試一下,怎麼辦呢?這點也是很現實的一個問題。咱們是否能夠針對這個接口來簡單實現一個代理類,來測試模擬,指望代碼生成本身的結果呢?幸運的是,有一種測試模式能夠幫助咱們:mock對象。Mock對象也就是真實對象在調試期的替代品。web

何時須要使用Mock?

關於何時須要Mock對象,Tim Mackinnon給咱們了一些建議:sql

  • 真實對象具備不可肯定的行爲(產生不可預測的結果,如股票的行情)
  • 真實對象很難被建立(好比具體的web容器)
  • 真實對象的某些行爲很難觸發(好比網絡錯誤)
  • 真實狀況令程序的運行速度很慢
  • 真實對象有用戶界面
  • 測試須要詢問真實對象它是如何被調用的(好比測試可能須要驗證某個回調函數是否被調用了)
  • 真實對象實際上並不存在(當須要和其餘開發小組,或者新的硬件系統打交道的時候,這是一個廣泛的問題)

如何使用Mock?

.NET Mock Framework有哪些,能夠看看下面幾個網頁:數據庫

關於Mock框架的實現方式,大概有兩種:基於動態代理實現;基於編譯時靜態織入實現。各個框架的用法看一下介紹很快就能夠掌握了,關鍵是如何使用各類mock技術,存在的爭論主要有下面幾個:編程

  • 爭論一:像Typemock、Moles、Visual Studio 2012 Fakes Framework這類靜態織入技術的框架,能夠支持對Sealed Class、Non-Abstract Method、Non-Virtual Method、Static Method的Mock。有些人以爲這很強大,有些人以爲這反倒很差,他們認爲像Moq、Rhino Mocks這類的框架,正由於不支持前面說的四類狀況的mock,強迫項目必須實現依賴倒置,從而下降了項目的耦合性,以達到較高的可測試性以及可維護性。
  • 爭論二:在使用動態代理方式的Mock框架時候,爲了「可測試性」,protected方法必須是virtual的,由於咱們須要在子類中進行override。同理,Mock框架可以輔助的方法也必須是virtual的,即便是一個public方法。那麼,您以爲這是爲了可測試性而作出的讓步嗎?或者換句話說,您以爲,一個不能夠override的protected方法,可是會影響到其餘公開接口的功能,這是否是一個合理的設計呢?若是這是一個合理的設計,又不想做出這樣的讓步……咱們又該怎麼作呢?(這段話摘自老趙的「與protected成員有關的單元測試方式」)
  • 爭論三:在使用動態代理方式的Mock框架時候,爲了測試一些Non-Abstract Method、Non-Virtual Method、Static Method,提供一個被測方法/類的Wrapper,封裝對沒法直接訪問方法的調用,是否合適?作法參考:
    http://blog.zhaojie.me/2009/08/unit-test-protected-method.html#comment_iX2whQ8q04I003i2
    http://blog.zhaojie.me/2009/08/unit-test-protected-method.html#comment_iX2whQ8q04I003hi

關於爭論一,個人考慮的結果以下:

實際狀況中,我會根據項目實際狀況來選型。考慮的因素主要有:安全

  • 是否須要支持私有方法、Non-virtual方法的單元測試:實際狀況中,項目的代碼結構不必定是想象中的理想狀況,這個時候就須要考慮Typemock、Visual Studio 2012 Fakes這類框架。
  • 開發效率:可以花最小的成本完成單元測試工做,得到最大的收益。使用複雜,開發效率低的框架的優先級天然要排在後面。
  • 集成難易程度:通常單元測試用例會在提交代碼的時候跑一遍,做爲保證提交代碼質量的一道關卡。單元測試框架是否能和現有持續集成工具很好的集成在一塊,也是要考慮的因素。
  • 運行效率:跑的越快的框架,可以減小每次驗證的時間成本。

什麼是「測試驅動數據庫開發」?

測試驅動數據庫開發,也稱爲TDDD(Test-Driven Database Development),是把TDD的理念運用到數據庫開發的過程當中,經過數據庫測試來定義數據庫的行爲,如同經過測試定義應用程序代碼邏輯同樣,來保證數據庫重構過程當中的質量。網絡

使用 TDDD 的優勢包括:app

  • 首先,全部TDD的優勢都適用與TDDD ,你能夠小步而安全的前進;
  • 經過重構使系統在整個生命週期中保持高質量的設計;
  • 迴歸測試讓你能儘早發現缺陷;
  • TDDD促使你能時刻得到一個最新的可執行的系統(而不像傳統的設計文檔)。

推薦感興趣的朋友看看伍斌老師翻譯《測試驅動數據庫開發——Test-Driven Database Development: Unlocking Agility》這本書:

目錄結構:http://my.safaribooksonline.com/book/databases/database-design/9780132776486

伍斌老師的譯者序:讓數據庫應用開發再也不裸奔——Test-Driven Database Development譯者序

樣章試讀:http://ptgmedia.pearsoncmg.com/images/9780321784124/samplepages/032178412X.pdf

原做者Max Guernsey的PPT:http://www.maxthe3rd.com/test-driven-database-development/TDD-Database.pdf

如何作測試驅動數據庫開發?

因爲這塊研究不深,暫時列舉一些數據庫單元測試框架,將來若是研究更加深刻了,再專門寫文章介紹。

數據庫單元測試的框架:

 

參考:

相關文章
相關標籤/搜索