2011-05-19 123 views
2

我已經閱讀了很多關於單元測試的知識,但是我仍然沒有找到任何可以證明爲什麼單元測試值得花時間的好例子。單元測試示例證明單元測試值得一寫

我想看看實際的Java代碼,它展示瞭如何完成單元測試以及如何捕捉可能的錯誤。

+3

單元測試「值得」做什麼的「證明」標準是什麼?單元測試提供了自動化迴歸測試,使您的代碼更易於更改(並知道您的更改沒有破壞以前的工作代碼)。當單元測試獲得一個迴歸時,「證明」就出現了,否則在部署到生產環境之前,這種回退是不可能發現的,這可能令人尷尬,對用戶造成實際損害等。單個單元測試的代碼不提供任何具體的「證明」。 – 2011-05-19 07:23:21

+1

人們很愚蠢,所以他們犯錯誤(我也不例外)。單元測試可以幫助你追蹤那些愚蠢的錯誤。 – 2011-05-19 07:24:00

+0

你在質疑單元測試或自動化測試背後的基本原理嗎? – ponzao 2011-05-19 07:38:54

回答

6

單元測試不是爲了捕捉可能的錯誤,它關於「感覺有點安全」。比較好的例子是一個代碼庫比擁有多個開發者的hello world更大的項目。只有時間的問題,當有人破壞某些東西時,以前工作的是什麼。問題是 - 你什麼時候知道?應用程序部署後還是在開發過程中?

+1

+1:迴歸測試(檢查現有的功能以確保它未被代碼的後續修改所破壞)是單元測試在我看來最大的好處之一 - 特別是當您正在開發一個開發人員不知道這個ins的大型項目時以及每段代碼的缺失,因此可能會通過錯誤地使用其他開發人員編寫的代碼來引入錯誤。 – 2011-05-19 07:46:29

+1

我認爲這比信心更強,但我同意你的觀點。我想強調的是,測試需要表示正確的功能,而不是自助服務的實現細節。單元測試不能保證零缺陷或使代碼的質量本質上更好。在開發過程中投入思想時,我們可以獲得好處 - 我們認爲代碼需要做的事情,它的生命週期和使用情況 - 構建錯誤早日實現,並且設計會影響可擴展性。這是一種思維和工藝,你在練習時會變得更好。 – bryanbcook 2011-05-20 10:06:52

0

我有一個例子,當我希望我有單元測試。

我們使用裝飾器模式將IBitmapStream從一種格式轉換爲另一種格式,並使用許多BitmapConverter類。一個BitmapConvertor類本身就是一個IBitmapStream: BitmapConverters

我們有許多位圖轉換器,以位深度,色彩空間轉換(灰度,RGB,CMYK),排填充,顏色分量排序,特效轉換,.. 。

我們沒有進行自動測試。因此,當我們修復任何單個轉換器中的錯誤時,需要大量的人工紀律和努力,通過我們的GUI和許多不同的測試位圖來測試轉換器。

這些錯誤往往是微妙的 - 當我們測試了多個鏈接在一起的轉換器時,它們首先變得明顯 - 並且修飾器模式的缺點是調試困難。 修復一個bug往往導致另一個案件。

如果我們有一套自動化的測試,它會節省大量的時間和精力。

對於我們QM部門(或客戶)發現的每個錯誤,我們在開發時都會首先編寫一個單元測試來複制該錯誤,然後修復代碼,並確保該修復沒有打破任何其他測試。

1

除了其他評論者所描述的好處之外,我認爲單元測試和自動化單元測試對生產代碼的設計具有積極的影響。設計可測試的代碼往往會導致更鬆散耦合的設計,其優點被廣泛記錄。

+0

+1我絕對同意這個答案。思考如何在編寫代碼時測試代碼,這往往會導致整個代碼中的問題更好地分離,並且組件和類之間的依賴關係降至最低。 – GarethOwen 2011-05-19 09:27:28

0

我不能沒有一些解釋就舉個例子。編寫單元測試非常耗時。因此,很難說服管理人員和同事們的價值。我在開發的編碼階段編寫單元測試,它可以將編碼時間延長50 - 100%。

它值得嗎?我想是這樣。單元測試在與其他代碼模塊集成之前查找錯誤。另外,如果他們正確地檢查了大多數運行方案,那麼在開發完成後(維護),它們在查找破損代碼方面非常有效。

這裏有一個簡單的例子,如何使用JUnit 4.x版:

public class UnitTests { 
    @org.junit.Test 
    public void test() { 
     A a = new A(); 
     String s = " Hello "; 
     String result = a.trim(s); 

     assertEquals("The String wasn't trimmed", "Hello", result); 
    } 
} 

public class A { 
    public String trim(String s) { 
     return s.trim(); 
    } 
} 

由於String.trim()將同時刪除開頭和結尾的空白,而且由於字符串s包含前沿和後的空格,如果有人稍後更改方法A.trim()以執行其他操作,例如僅修剪前導或尾隨空白,則此測試將失敗。