天天看點

《JUnit實戰(第2版)》—— 1.1 證明它能運作

本節書摘來異步社群《junit實戰(第2版)》一書中的第1章,第1.1節,作者:【美】petar tahchiev , felipe leme , vincent massol , gary gregory,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

junit實戰(第2版)

為了我們的第一個示例,我們建立一個簡單的calculator類,可以将兩個數相加。calculator類為了用戶端提供了一個api,但并沒有包含一個使用者界面,如代碼1.1所示。

代碼1.1 用于測試的calculator類

《JUnit實戰(第2版)》—— 1.1 證明它能運作

雖然這裡沒有列出文檔,但calculator的add(double,double)方法的意圖顯然是接受兩個double值并以double類型傳回它們的和。雖然編譯器能夠告訴我們它通過了編譯,但是我們也應該確定它在運作期間能夠正常工作。單元測試的核心原則是“任何沒有經過自動測試的程式功能都可以當作不存在1”。add方法代表了calculator的一個核心功能。我們擁有了一些能夠實作該功能的代碼,現在缺少的隻是一個證明實作能夠正常工作的自動測試。

add方法如此簡單怎麼可能出錯?

目前add方法的實作非常簡單,以緻不可能出錯。假如add隻是一個不重要的工具方法,那麼我們可能就不會直接測試它。在這種情況下,如果add出錯,那麼針對使用add的所有方法的所有測試都将會出錯。于是,add方法将被間接測試,雖然如此,但還是算被測試過了。在calculator程式中,add不隻是一個方法,而且是一項程式功能。為了確定程式正确運作,大部分開發人員都會期待一個針對add功能的自動測試,無論實作看起來多麼簡單。在某些情況下,我們可以通過自動功能測試或自動驗收測試來證明程式功能。關于軟體測試的一般内容,可以參閱本書的第3章内容。

在這個時候進行任何測試看起來都會有些困難。因為我們甚至都沒有使用者界面可以輸入一對double值。我們可以編寫一個指令行小程式,它能夠在我們輸入兩個double值後顯示運作結果。這樣一來,就同時測試了我們自己輸入數字及求和的能力了。這可比我們想要的還要多。我們想要知道的是,這個工作單元是否能夠對兩個double值求和并且傳回正确的值,而并沒想測試程式員是否能夠輸入數字!

與此同時,如果想花大力氣測試我們的工作成果,那麼也應該盡量使得這一份投入物有所值。在我們編寫add(double,double)方法時,知道它能夠正常工作這固然很好,但是我們真正想知道的是,在傳遞應用程式的其他部分後或者在任何時候進行了後續的修改,這個方法是否依然夠能正常工作。如果我們把這些需求放在一起考慮,那麼我們就會産生一個想法:為add方法編寫一個簡單的測試。

這個測試程式可以将已知的值傳給方法,并判斷運作結果是否與我們的預期一緻。我們也可以随後再次運作該程式,以確定該方法能夠随着應用程式的增長而持續正常工作。我們能夠編寫的最簡單的測試程式是什麼樣的呢?如代碼1.2所示的calculatortest程式怎麼樣呢?

代碼1.2 一個簡單的calculatortest程式

《JUnit實戰(第2版)》—— 1.1 證明它能運作

第一個calculatortest非常簡單。它建立了calculator的一個執行個體,傳遞給它兩個數字,并且檢查運作結果。如果運作結果與我們的預期不一緻,那麼我們就在标準輸出裝置上輸出一條消息。

如果現在我們編譯并運作這個程式,那麼測試将會正常通過,同時一切看上去都非常順利。但是如果我們修改代碼使其報錯,那麼将會發生什麼呢?為了找出錯誤資訊,我們将不得不仔細地盯着螢幕。我們可能不必提供輸入資訊,但是我們仍然在測試我們自己監控程式輸出的能力。我們想要測試的是代碼,而不是我們自己!

在java中,表示錯誤條件的傳統做法是抛出異常。是以,我們要抛出異常來表示測試失敗。

與此同時,我們或許還想針對其他尚未編寫的calculator方法運作測試,如subtract或multiply。轉向子產品化的設計可以使得捕捉和處理異常更為容易,也可以使得以後擴充測試程式更為簡單。代碼1.3展示了稍好一點的calculatortest程式。

代碼1.3 稍好一點的calculatortest程式

《JUnit實戰(第2版)》—— 1.1 證明它能運作

來看代碼1.3,在..lucene實戰1.tif部分,我們把測試轉移到了它自己的testadd方法中。現在要觀察測試做了些什麼更加容易了。我們稍後也可以增加更多的方法,編寫更多的單元測試,而不會使main方法變得更加難以維護。在..lucene實戰2.tif部分,我們修改了main方法,以便在發生錯誤時輸出棧跟蹤資訊,然後,如果發生任何錯誤,就抛出一個總結性的異常結束運作。

既然你已經了解了一個簡單的應用程式及其測試,那麼你就能夠發現,即使這種不重要的類及其測試都可以從少量的腳手架代碼(scaffolding code)中受益——我們建立腳手架代碼來運作和管理測試結果。由于應用程式變得越來越複雜、涉及的測試也越來越多,繼續建構和維護我們自己自定義的測試架構已成為一個負擔。

接下來,我們退一步,來看一下單元測試架構的一般情況。

1kent beck, extreme programming explained: embrace change (reading, ma: addison-wesley, 1999)。

本文僅用于學習和交流目的,不代表異步社群觀點。非商業轉載請注明作譯者、出處,并保留本文的原始連結。