我的JAVA成長之路==>單元測試與迴歸測試

原文鏈接:http://www.cnblogs.com/xinz/archive/2011/11/20/2255830.html

這裏只是爲了防止原鏈接失效或被刪除導致無法找到該資源所以在此備份
如果涉及到侵權還望通知一下, 本人立刻刪除.

1.2 好的單元測試的標準

單元測試應該準確、快速地保證程序基本模塊的正確性。下面是驗證單元測試好壞的一系列標準:

單元測試應該在最低的功能/參數上驗證程序的正確性。

單元測試應該測試程序中最基本的單元——如在C++/C#/Java中的類,在此基礎上,可以測試一些系統中最基本的功能點(這些功能點由幾個基本類組成),從面向對象的設計原理出發,系統中最基本的功能點也應該由一個類及其方法來表現。單元測試要測試API中的每一個方法及每一個參數。

單元測試必須由最熟悉代碼的人(程序的作者)來寫。

代碼的作者最瞭解代碼的目的、特點和實現的侷限性。所以,寫單元測試沒有比作者更適合的人選了。

問:如果我很忙,能不能讓別人代勞做單元測試?

答:如果忙到連單元測試都沒有時間做,那麼你也沒有時間寫好這個功能。在一些極限編程的方法中,是可以考慮讓別人來做單元測試的,但是,程序的作者還是要對單元測試負責。

最好是在設計的時候就寫好單元測試,這樣單元測試就能體現API的語義,如果沒有單元測試,語義的準確性就不能得到保障,以後會產生歧義。

單元測試過後,機器狀態保持不變。

這樣就可以不斷地運行單元測試,如果單元測試創建了臨時的文件或目錄,應該在Teardown階段把這些臨時的文件或目錄刪除。

如果單元測試在數據庫中創建或修改了記錄,那麼也許要刪除這些記錄,或者每一個單元測試使用一個新的數據庫,這樣可以保證單元測試不受以前單元測試實例的干擾。

單元測試要快(一個測試運行時間是幾秒鐘,而不是幾分鐘)。

快,才能保證效率。因爲一個軟件中有幾十個基本模塊(類),每個模塊又有幾個方法,基本上我們要求一個類的測試要在幾秒鐘內完成。如果軟件有相互獨立的幾個層次,那麼在測試組中可以分類,如數據庫層次、網絡通信層次、客戶邏輯層次和用戶界面層次,可以分類運行測試,比如只修改了“用戶界面”的代碼,則只需運行“用戶界面”的單元測試。

單元測試應該產生可重複、一致的結果。

如果單元測試的結果是錯的,那一定是程序出了問題,而且這個錯誤一定是可以重複的。

問:如果用隨機數以增加測試的真實性,好麼?

答:一般情況下不好,如果某個隨機數導致程序出錯,但是下一次運行又不能重複這一錯誤,於事無補。要注意我們還是要用隨機數等辦法“增加測試的真實性”,但是不是在單元測試中。單元測試不能解決所有問題,所以也不必期望它會發現所有的缺陷。

獨立性,單元測試的運行/通過/失敗不依賴於別的測試,可以人爲構造數據,以保持單元測試的獨立性。

程序中的各個模塊都是互相依賴的,否則它們就不會出現在一個程序中。一般情況下,單元測試中的模塊可以直接引用其他的模塊,並期待其他的模塊能返回正確的結果。

如果其他的模塊很不穩定,或者其他模塊運行比較費時(如進行網絡操作),而且對於本模塊的正確性並不起關鍵的作用,這時可以人爲地構造數據以保證這個單元測試的獨立性。

單元測試應該覆蓋所有代碼路徑,包括錯誤處理路徑,爲了保證單元測試的代碼覆蓋率,單元測試必須測試公開的和私有的函數/方法。

單元測試必須覆蓋所測單元的所有代碼路徑。

問:啊!這樣豈不是要寫很多囉裏囉唆的測試方法?

答:對,因爲程序中很多缺陷都是從這些囉裏囉唆的錯誤處理中產生的。如果你的模塊中某個錯誤處理路徑很難到達,那你也許要想想是否可以把這個錯誤處理拿掉。

大栓:這對於那些愛寫複雜代碼的人是一個很好的懲罰,不對,是一個很好的鍛鍊。

阿超:對,把單元測試的責任和代碼作者綁定在一起後,代碼作者就能更真切地體會到複雜代碼的副作用,因爲驗證複雜代碼的正確性要困難得多。要注意的一點是:100%的代碼覆蓋率並不等同於100%的正確性。在下面的情況下,100% 的覆蓋率和100% 的正確性不是同一回事:

 a) 代碼中並沒有處理錯誤情況。 例如代碼打開了文件,但是並沒有處理一些異常情況,例如文件不存在,權限有問題,等等

 b) 代碼中有效能問題,雖然代碼執行了,並且也正確地返回了。但是代碼執行得也許非常慢。

 c) 多線程環境中的同步問題, 這個問題和本地代碼執行與否關係不大。

 d) 其它和外部條件相關的問題 (例如和設備相關,和網絡相關的問題)

單元測試應該集成到自動測試的框架中。

另一個重要的措施是要把單元測試自動化,這樣每個人都能很容易地運行它,並且可以使單元測試每天都運行。每個人都可以隨時在自己的機器上運行。團隊一般是在每日構建中運行單元測試的,這樣每個單元測試的錯誤就能及時被發現並得到修改。

單元測試必須和產品代碼一起保存和維護。

單元測試必須和代碼一起進行版本維護。如果不是這樣,過了一陣,代碼和單元測試就會出現不一致,而且所有代碼的作者要花時間來確認哪些是程序出現的錯誤,哪些是由於單元測試更新滯後造成的錯誤。這樣就失去了單元測試的意義,同時又給大家增加了負擔。如此折騰多次以後,大家就會覺得維護單元測試是一件很費時費力的事。

很多開發人員有這樣那樣的藉口不去提高單元測試的覆蓋率, 其中一個就是: 這一部分代碼永遠測不到! 請看 MSDN 的視頻講解:

http://channel9.msdn.com/Events/Build/2012/3-015

1.3 迴歸測試

在單元測試的基礎上, 我們就能夠建立關於這一模塊的迴歸測試 (Regression Test).

Regress 的英語定義是: return to a worse or less developed state。是倒退、退化、退步的意思。

在軟件項目中,如果一個模塊或功能以前是正常工作的,但是在一個新的構建中出了問題,那這個模塊就出現了一個“退步”(Regression),從正常工作的穩定狀態退化到不正常工作的不穩定狀態。

在一個模塊的功能逐步完成的同時,與此功能有關的測試用例也同樣在完善中。一旦有關的測試用例通過,我們就得到了此模塊的功能基準 (Baseline) , 一個模塊的所有單元測試就是這個模塊最初的Baseline。

假如,在3.1.5版本,模塊A的測試用例125是通過的,但是測試人員發現在新的版本3.1.6,這個測試用例卻失敗了,這就是一個“倒退”。在新版本上運行所有已通過的測試用例以驗證有沒有“退化”情況發生,這個過程就是一個“Regression Test”。如果這樣的“倒退”是由於模塊的功能發生了正常變化(由於設計變更的原因)引起的,那麼測試用例的基準就要修改,以便和新的功能保持一致。

針對一個Bug Fix, 我們也要作Regression Test。

(1)驗證新的代碼的確把缺陷改正了。

(2)同時要驗證新的代碼沒有把模塊的現有功能破壞,沒有Regression。

所以對於“迴歸測試”中的“迴歸”,我們可以理解爲“迴歸到以前不正常的狀態”。

迴歸測試最好要自動化,因爲這樣就可以對於每一個構建快速運行所有迴歸測試,以保證儘早發現問題。單元測試是迴歸測試的基礎.

在專注於模塊基本功能的單元測試之外, 還有功能測試 – 從用戶的角度檢查功能完成得怎麼樣。 在微軟的實踐中,在一個項目的最後穩定階段,所有人都要參加全面的測試工作,把所有以前發現並修復的bug 找出來, 一個一個驗證, 以保證所有已經修復過的Bug的確得到了修復,並且沒有在最後一個版本中“復發”, 這是一個大規模的、全面的“迴歸測試”。

光說不練怎麼行,請看JUnit 教程:

  https://www.tuicool.com/articles/fArMFjJ

  http://www.cnblogs.com/rocedu/p/6371315.html#SECUNITTEST

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章