利用Ant使測試自動化
如前面所述,測試運行器是非常原始的。如果你正在運行Ant來編譯你的工程,那麼編譯文件是運行單元測試的好方法。(關於Ant的介紹,請參考我的文章《Ant簡介》(Starting with Ant),發表於Oracle雜誌2002年11/12月號中)。
假設你的源文件在src目錄中,所生成的類在tmp目錄中,並且junit.jar庫位於工程的libdirectory目錄中,那麼你可以編譯Java源文件,並使用清單3中所示的編譯文件(在工程的根目錄中)運行單元測試。
這個編譯文件的核心是運行單元測試的測試目標。運行這些測試是這個目標junit的唯一任務。爲了運行這一可選任務,必須首先將junit.jar庫放到Ant安裝目錄下的lib目錄中,然後下載並安裝同一目錄中的Ant可選任務庫。清單3中的示例嵌套了一個classpath類,它包括JUnit庫和工程的類;示例中還嵌套了一個batchtest元素,它利用一個選擇適當源文件的fileset元素定義了將要運行的測試。這個任務還包括haltonfilure和haltonerror屬性,它們告訴Ant在遇到一個失敗或錯誤時是否應當停止。如果將它們的值設置爲"真",那麼Ant在遇到第一個失敗或錯誤時將會停止,編譯將會失敗(顯然,這表示在運行測試過程中存在有問題)。另一方面,如果將它們的值設置爲"假",其結果就不是非常明確了(即使測試失敗,編譯也會成功),但所有測試仍將運行。printsummary屬性指示Ant是否顯示運行測試的輸出。數值withOutAndErr可以在開發測試時方便地告訴Ant顯示標準輸出和錯誤輸出。數值off表示不顯示任何內容,而on只顯示測試報告(沒有測試類的輸出)。junit任務具有很多屬性,詳細內容請參考Ant的文檔。
爲了測試這一編譯文件,你需要建立名字爲src、tmp和lib的目錄。將junit.jar庫放到lib目錄中,並將前面看到的示例Java源文件放到src目錄中。打開終端,進入該工程的根目錄,並輸入ant,其結果爲:
$ ant
Buildfile: build.xml
clean:
[delete] Deleting directory
/Users/casa/doc/oracle
/junit/prj/tmp
[mkdir] Created dir: /Users/casa
/doc/oracle/junit/prj/tmp
bin:
[javac] Compiling 4 source files
to /Users/casa/doc/oracle
/junit/prj/tmp
test:
[junit] Running IsoDateTest
[junit] Tests run: 1, Failures:
0, Errors: 0, Time elapsed:
0,005 sec
[junit] Running IsoDateTest2
[junit] Tests run: 2, Failures: 0,
Errors: 0, Time elapsed: 0,031 sec
[junit] Output:
[junit] setUp()
[junit] testIsoDate()
[junit] tearDown()
[junit] setUp()
[junit] testToString()
[junit] tearDown()
all:
BUILD SUCCESSFUL
Total time: 8 seconds
Ant還可以生成非常有用的HTML格式的測試報告。爲了生成這樣的報告,將前面的測試目標用以下目標代替:
<target name="test" depends="bin"
description="Run JUnit tests">
<junit haltonfailure="false"
printsummary="withOutAndErr">
<classpath refid="cp"/>
<batchtest todir="${tmp}">
<fileset dir="${src}"
includes="**/*Test*.java"/>
</batchtest>
<formatter type="xml"/>
</junit>
<junitreport todir="${tmp}">
<fileset dir="${tmp}"
includes="TEST-*.xml"/>
<report format="frames"
todir="${tmp}"/>
</junitreport>
</target>
這一目標與前面的目標相同,只是該目標在batchtext元素中增加了一個新的屬性--todir,它告訴Ant在tmp目錄中生成可擴展的標記語言(XML)報告。該目標還增加了一個新的junitreport元素,以便由XML文件生成一個HTML報告。這一元素要求在安裝Ant的lib目錄中安裝Xalan庫(詳細內容見Ant文檔的junitreport部分:ant.apache.org/manual/install.html)。這一元素還定義了使用todir屬性生成的文件的目標目錄。通過嵌套一個fileset元素來定義爲生成這一報告而需要處理的XML文件。期望的輸出格式利用嵌套的報告元素來實現。該對象將生成一個諸如圖4所示的報告。
這類報告在使單元測試自動運行時特別有用(比如在夜間編譯期間)。在這些情況下,錯誤或失敗不會中斷測試,因此你必須將前面提到的junit任務的haltonfailure和haltonerror屬性設置爲"假"。這一報告對於衡量實施進程也非常有用(比如當你必須重寫已有代碼時,或者在實施之前已經編寫了測試的情況下)。
Ant對啓動JUnit圖形運行器也非常有用。下面的對象將會啓動Swing測試運行器:
<target name="testui" depends="bin"
description="Run graphical JUnit">
<java classname="junit.swingui.TestRunner"
classpathref="cp"
fork="true"/>
</target>
你應當在終端中運行這一對象,並且在另一個終端或你喜歡的IDE中使用Ant對其進行編譯。這種方式使你不必在每次想要測試代碼時都啓動圖形運行器。
在Oracle9i Jdeveloper中的JUnit集成
Oracle9i JDeveloper並沒有基於網絡集成JUnit,但是下載並安裝這一插件只需要幾分鐘的時間。爲了完成此過程,選擇JDeveloper的"Help"菜單下的"Check for Updates"項。這樣將會打開IDE更新嚮導,以連接到Oracle技術網站,下載該插件並安裝它。當安裝該插件後,需要關閉並重啓Oracle9i JDeveloper。注意,嚮導還會下載相關的文檔。
通過爲每個任務提供嚮導,這個插件極大地提高了開發人員編寫測試實例、測試包和fixture等的工作效率。要調用這些嚮導,點擊"File"菜單下的"New"項,然後選擇"General/Unit Tests"類,並從右側的窗體中選擇合適的嚮導。你也可以從界面上啓動測試套件。
當準備好對項目進行代碼測試後,應當首先使用專用嚮導來編寫fixture,然後測試實例嚮導可以利用它們集成到測試實例中。另外,還有一些用來生成自定義測試fixture的嚮導以及生成商務組件和數據庫連接測試fixture的嚮導。這後兩種嚮導生成專用代碼,以使用setUp()和tearDown()方法設置和發佈商務組件或數據庫連接。
當完成fixture後,下一步應當使用合適的嚮導來生成測試實例,這些嚮導可以讓你選擇要測試的類和方法。你還可以選擇在這個測試中使用的fixture。這將生成一個使用測試方法的主體完成的代碼框架。最後應當生成套件來運行你的測試。這個專用嚮導讓你選擇要包括在套件中的測試,併爲你生成整個類。要啓動一個測試套件,點擊瀏覽器中的文件,並選擇Run。這將會啓動圖形界面並運行套件的測試。
在"Help"菜單中選擇"Help Topics",你將會在JDeveloper文檔中找到關於如何使用這些嚮導的詳細教程。這會打開幫助系統窗口。點擊"Unit Testing with JUnit"項,然後選擇合適的教程。
JUnit和JDeveloper之間的這種集成使你能夠只編寫單元測試中你感興趣的那部分的代碼,而讓工具爲你編寫重複的代碼。
JUnit最佳實踐
下面是一些在使用JUnit時應當注意的技巧:
- 在實施之前編寫測試代碼。這是一種合同驅動的實施方式。
- 只測試那些可能會中斷的方法(也就是說,在多數情況下不應測試setter和getter方法)。要儘可能地多進行測試,以避免迴歸測試。當測試一個較大的應用程序時,你可以在夜間編譯時運行所有測試。
- 一定要使用正確的JUnit擴展來測試特殊的應用程序(如使用Castus測試J2EE應用程序)。
值得花費的時間
到現在,你應當已經清楚地知道使用JUnit框架和合適的工具實施單元測試是多麼快速而簡單。關於單元測試的下一個目標是使你的CTO相信你在實施測試時所必須花費的時間是爲了以後節省更多的時間。但是,當你考慮在檢查老代碼、修正錯誤和發佈一個調試過的版本上所花費的時間(它可能花費整個一天)時,在開發過程的早期階段捕獲的代碼錯誤毫無疑問是一項很好的投資。這裏並沒有考慮當錯誤代碼不再位於塊的頂部時開發人員必須遵循的"black magic"步驟,這些步驟包括:標記代碼,製作一個分支、修正代碼錯誤、進行發佈,以及將代碼修正合併到塊中。所有這些步驟都非常耗時,並且容易產生錯誤。
要開始使用單元測試和JUnit,請訪問JUnit網站: www.junit.org。你將找到大量有用的文檔(包括使用JUnit實施測試的詳細說明書)、一個與JUnit集成的IDE列表,以及關於JUnit擴展工具的詳細內容。
Michel Casabianca ( [email protected])是In-Fusio(一家爲移動用戶提供遊戲服務的法國公司)的一名軟件工程師,同時也是XML Pocket Reference(O'Reilly出版,2001年)一書的合著者。
表1:編寫測試實例中所使用的判定方法
| assertEquals(期望原型,實際原型) |
檢查兩個原型是否相等 | assertEquals(期望對象,實際對象) |
利用對象的equals()方法檢查兩個對象是否相等 | assertSame(期望對象,實際對象) |
檢查具有相同內存地址的兩個對象是否相等 | assertNotSame(期望對象,實際對象) |
檢查具有不同內存地址的兩個對象是否不相等 | assertNull(對象 對象) |
檢查一個對象是否爲空 | assertNotNull(對象 對象) |
檢查一個對象是否爲非空 | assertTrue(布爾條件) |
檢查條件是否爲真 | assertFalse(布爾條件) |
檢查條件是否爲假 |
|