<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Terry.Li-彬

    虛其心,可解天下之問;專其心,可治天下之學(xué);靜其心,可悟天下之理;恒其心,可成天下之業(yè)。

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      143 隨筆 :: 344 文章 :: 130 評論 :: 0 Trackbacks

    要使測試自動化,您需要一個(gè)測試框架。您可以自己開發(fā)或購買,也可以使用某些開放源代碼工具,例如 JUnit。我選擇 JUnit 出于以下幾個(gè)原因:

    • 不需要編寫自己的框架。
    • 它是開放源代碼,因此不需要購買框架。
    • 開放源代碼社區(qū)中的其他開發(fā)者會使用它,因此可以找到許多示例。
    • 它可以讓我將測試代碼與產(chǎn)品代碼分開。
    • 它易于集成到我的構(gòu)建過程中。

    測試布局
    圖 1 顯示了使用樣本 TestSuite 的 JUnit TestSuite 布局。每個(gè)測試都由若干單獨(dú)的測試案例構(gòu)成。每個(gè)測試案例都是一個(gè)單獨(dú)的類,它擴(kuò)展了 TestClass 類并包含了我的測試代碼,即那些曾在 main() 中出現(xiàn)的代碼。在該例中,我向 TestSuite 添加了兩個(gè)測試:一個(gè)是 SkeletonTest,我將它用作所有新類和 HelloWorld 類的起點(diǎn)。


    圖 1. TestSuite 布局

    測試類 HelloWorldTest.java
    按照約定,測試類的名稱中包含我所測試的類的名稱,但將 Test 附加到結(jié)尾。在本例中,我們的測試類是 HelloWorldTest.java 。我復(fù)制了 SkeletonTest 中的代碼,并添加了 testSayHello() 來測試 sayHello() 。請注意 HelloWorldTest 擴(kuò)展了 TestCase。JUnit 框架提供了 assertassertEquals 方法,我們可以使用這些方法來進(jìn)行驗(yàn)證。 HelloWorldTest.java 顯示在清單 2 中。


    清單 2. HelloWorldTest.java
    package test.com.company;import com.company.HelloWorld; import junit.work.TestCase;import junit.work.AssertionFailedError;/** * JUnit 3.2 testcases for HelloWorld */ public class HelloWorldTest extends TestCase { public HelloWorldTest(String name) { super(name); } public static void main(String args[]) { junit.textui.TestRunner.run(HelloWorldTest.class); } public void testSayHello() { HelloWorld world = new HelloWorld(); assert( world!=null ); assertEquals("Hello World", world.sayHello() ); }}

    testSayHello() 看上去和 HelloWorld.java 中原來的 main 方法類似,但有一個(gè)主要的不同之處。它不是執(zhí)行 System.out.println 并顯示結(jié)果,而是添加了一個(gè) assertEquals() 方法。如果兩個(gè)值不同, assertEquals 將打印出兩個(gè)輸入的值。您可能已經(jīng)注意到這個(gè)方法不起作用!HelloWorld 中的 sayHello() 方法不返回字符串。如果我先寫過測試,就會捕捉到這一點(diǎn)。我將 "Hello World" 字符串與輸出流聯(lián)結(jié)起來。這樣,按照清單 3 中顯示的那樣重寫了 HelloWorld,去掉 main() ,并更改了 sayHello() 的返回類型。


    清單 3. Hello world 測試案例。
    package com.company;public class HelloWorld { public String sayHello() { return "Hello World"; }}

    如果我保留了 main() 并修改了聯(lián)系,代碼看上去如下:
    public static void main( String[] args ) { HelloWorld world = new HelloWorld(); System.out.println(world.sayHello()); }

    新的 main() 與我測試程序中的 testSayHello() 非常相似。是的,它看上去不象是一個(gè)現(xiàn)實(shí)世界中的問題(這是人為示例的問題),但它說明了問題。在單獨(dú)的應(yīng)用程序中編寫 main() 可以改進(jìn)您的設(shè)計(jì),同時(shí)幫助您設(shè)計(jì)測試?,F(xiàn)在我們已經(jīng)創(chuàng)建了一個(gè)測試類,讓我們使用 Ant 來將它集成到構(gòu)建中。





    回頁首


    使用 Ant 將測試集成到構(gòu)建中

    Jakarta Project 將 Ant 工具說成“不帶 make 缺點(diǎn)的 make”。Ant 正在成為開放源代碼世界中實(shí)際上的標(biāo)準(zhǔn)。原因很簡單:Ant 是使用 Java 語言編寫的,這種語言可以讓構(gòu)建過程在多種平臺上使用。這種特性簡化了在不同 OS 平臺之間的程序員的合作,而合作是開放源代碼社區(qū)的一種需要。您可以在自己選擇的平臺上進(jìn)行開發(fā) 構(gòu)建。Ant 的特性包括:

    • 類可擴(kuò)展性 Java 類可用于擴(kuò)展構(gòu)建特性,而不必使用基于 shell 的命令。
    • 開放源代碼 因?yàn)?Ant 是開放源代碼,因此類擴(kuò)展示例很充足。我發(fā)現(xiàn)通過示例來學(xué)習(xí)非常棒。
    • XML 可配置 Ant 不僅是基于 Java 的,它還使用 XML 文件配置構(gòu)建過程。假設(shè)構(gòu)建實(shí)際上是分層的,那么使用 XML 描述 make 過程就是其邏輯層。另外,如果您了解 XML,要學(xué)習(xí)如何配置構(gòu)建就更簡單一些。

    圖 2 簡要介紹了一個(gè)配置文件。配置文件由目標(biāo)樹構(gòu)成。每個(gè)目標(biāo)都包含了要執(zhí)行的任務(wù),其中任務(wù)就是可以執(zhí)行的代碼。在本例中, mkdir是目標(biāo) compile的任務(wù)。 mkdir是建立在 Ant 中的一個(gè)任務(wù),用于創(chuàng)建目錄。 Ant 帶有一套健全的內(nèi)置任務(wù)。您也可以通過擴(kuò)展 Ant 任務(wù)類來添加自己的功能。

    每個(gè)目標(biāo)都有唯一的名稱和可選的相關(guān)性。目標(biāo)相關(guān)性需要在執(zhí)行目標(biāo)任務(wù)列表之前執(zhí)行。例如圖 2 所示,在執(zhí)行 compile 目標(biāo)中的任務(wù)之前需要先運(yùn)行 JUNIT 目標(biāo)。這種類型的配置可以讓您在一個(gè)配置中有多個(gè)樹。


    圖 2. Ant XML 構(gòu)建圖

    與經(jīng)典 make 實(shí)用程序的相似性是非常顯著的。這是理所當(dāng)然的,因?yàn)?make 就是 make。但也要記住有一些差異:通過 Java 實(shí)現(xiàn)的跨平臺和可擴(kuò)展性,通過 XML 實(shí)現(xiàn)的可配置,還有開放源代碼。

    下載和安裝 Ant
    首先下載 Ant(請參閱 參考資料 )。將 Ant 解壓縮到 tools 目錄,再將 Ant bin 目錄添加到路徑中。(在我的機(jī)器上是 e:"tools"ant"bin 。)設(shè)置 ANT_HOME 環(huán)境變量。在 NT 中,這意味著進(jìn)入系統(tǒng)屬性,然后以帶有值的變量形式添加 ANT_HOME。ANT_HOME 應(yīng)該設(shè)置為 Ant 根目錄,即包含 binlib 目錄的目錄。(對我來說,是 e:"tools"ant 。)確保 JAVA_HOME 環(huán)境變量設(shè)置為安裝了 JDK 的目錄。Ant 文檔有關(guān)于安裝的詳細(xì)信息。

    下載和安裝 JUnit
    下載 JUnit 3.2(請參閱 參考資料 )。解開 junit.zip ,并將 junit.jar 添加到 CLASSPATH。如果將 junit.zip 解包到類路徑中,可以通過運(yùn)行以下命令來測試安裝: java junit.textui.TestRunner junit.samples.AllTests

    定義目錄結(jié)構(gòu)
    在開始我們的構(gòu)建和測試過程之前,需要一個(gè)項(xiàng)目布局。圖 3 顯示了我的樣本項(xiàng)目的布局。下面描述了布局的目錄結(jié)構(gòu):

    • build -- 類文件的臨時(shí)構(gòu)建位置。構(gòu)建過程將創(chuàng)建這個(gè)目錄。
    • src -- 源代碼的位置。 Src 被分為 test 文件夾和 main 文件夾,前者用于所有的測試代碼,而后者包含可交付的代碼。將測試代碼與主要代碼分離提供了幾點(diǎn)特性。首先,使主要代碼中的混亂減少。其次,它允許包對 齊。我就熱衷與將類和與其相關(guān)的包放置在一起。測試就應(yīng)該和測試在一起。它還有助于分發(fā)過程,因?yàn)槟悴豢赡艽蛩銓卧獪y試分發(fā)給客戶。

    在實(shí)際中,我們有多個(gè)目錄,例如 distributiondocumentation 。我們還會在 main 下有多個(gè)用于包的目錄,例如 com.company.util 。

    因?yàn)槟夸浗Y(jié)構(gòu)經(jīng)常變動,所以在 build.xml 中有這些變動的全局字符串常數(shù)是很重要的。


    圖 3. 項(xiàng)目布局圖

    Ant 構(gòu)建配置文件示例
    下一步,我們要創(chuàng)建配置文件。清單 4 顯示了一個(gè) Ant 構(gòu)建文件示例。構(gòu)建文件中的關(guān)鍵就是名為 runtests 的目標(biāo)。這個(gè)目標(biāo)進(jìn)行分支判斷并運(yùn)行外部程序,其中外部程序是前面已安裝的 junit.textui.TestRunner 。我們指定要使用語句 test.com.company.AllJUnitTests 來運(yùn)行哪個(gè)測試套件。


    清單 4. 構(gòu)建文件示例

    <property name="app.name" ="sample" /> <property name="build.dir" ="build/classes" /> <target name="JUNIT"> <available property="junit.present" classname="junit.work.TestCase" /> </target> <target name="compile" depends="JUNIT"> <mkdir dir="${build.dir}"/> <javac srcdir="src/main/" destdir="${build.dir}" > <include name="**/*.java"/> </javac> </target> <target name="jar" depends="compile"> <mkdir dir="build/lib"/> <jar jarfile="build/lib/${app.name}.jar" basedir="${build.dir}" includes="com/**"/> </target> <target name="compiletests" depends="jar"> <mkdir dir="build/testcases"/> <javac srcdir="src/test" destdir="build/testcases"> <classpath> <pathelement location="build/lib/${app.name}.jar" /> <pathelement path="" /> </classpath> <include name="**/*.java"/> </javac> </target> <target name="runtests" depends="compiletests" if="junit.present"> <java fork="yes" classname="junit.textui.TestRunner" taskname="junit" fail="true"> <arg ="test.com.company.AllJUnitTests"/> <classpath> <pathelement location="build/lib/${app.name}.jar" /> <pathelement location="build/testcases" /> <pathelement path="" /> <pathelement path="${java.class.path}" /> </classpath> </java> </target> </project>

    運(yùn)行 Ant 構(gòu)建示例
    開發(fā)過程中的下一步是運(yùn)行將創(chuàng)建和測試 HelloWorld 類的構(gòu)建。清單 5 顯示了構(gòu)建的結(jié)果,其中包括了各個(gè)目標(biāo)部分。最酷的那部分是 runtests 輸出語句:它告訴我們整個(gè)測試套件都正確運(yùn)行了。

    我在圖 4 和圖 5 中顯示了 JUnit GUI,其中所要做的就是將 runtest 目標(biāo)從 junit.textui.TestRunner 改為 junit.ui.TestRunner 。當(dāng)您使用 JUnit 的 GUI 部分時(shí),您必須選擇退出按鈕來繼續(xù)構(gòu)建過程。如果使用 Junit GUI 構(gòu)建包,那么它將更難與大型的構(gòu)建過程相集成。另外,文本輸出也與構(gòu)建過程更一致,并可以定向輸出到一個(gè)用于主構(gòu)建記錄的文本文件。這對于每天晚上都要進(jìn) 行的構(gòu)建非常合適。


    清單 5. 構(gòu)建輸出示例
    E:"projects"sample>ant runtestsSearching for build.xml ... Build E:"projects"sample"build.xmlJUNIT:compile: [mkdir] Created dir: E:"projects"sample"build"classes [javac] Compiling 1 source file to E:"projects"sample"build"classesjar: [mkdir] Created dir: E:"projects"sample"build"lib [jar] Building jar: E:"projects"sample"build"lib"sample.jarcompiletests: [mkdir] Created dir: E:"projects"sample"build"testcases [javac] Compiling 3 source files to E:"projects"sample"build"testcases runtests: [junit] .. [junit] Time: 0.031 [junit] [junit] OK (2 tests) [junit]BUILD SUCCESSFULTotal time: 1 second 


    圖 4. JUnit GUI 測試成功


    圖 5. JUnit GUI 測試失敗





    回頁首


    了解測試的工作原理

    讓我們搞點(diǎn)破壞,然后看看會發(fā)生什么事。夜深了,我們決定把 "Hello World" 變成一個(gè)靜態(tài)字符串。在更改期間,我們 不小心打錯(cuò)了字母,將 "o" 變成了 "0",如清單 6 所示。
    清單 6. Hello world 類更改
    package com.company;public class HelloWorld { private final static String HELLO_WORLD = "Hell0 World"; public String sayHello() { return HELLO_WORLD; }}

    在建包時(shí),我們看到了錯(cuò)誤。清單 7 顯示了 runtest 中的錯(cuò)誤。它顯示了失敗的測試類和測試方法,并說明了為什么會失敗。我們返回到代碼中,改正錯(cuò)誤后離開。


    清單 7. 構(gòu)建錯(cuò)誤示例
    E:"projects"sample>ant runtestsSearching for build.xml ... Build E:"projects"sample"build.xmlJUNIT:compile:jar:compiletests:runtests: [junit] ..F [junit] Time: 0 [junit] [junit] FAILURES!!! [junit] Test Results: [junit] Run: 2 Failures: 1 Errors: 0 [junit] There was 1 failure: [junit] 1) testSayHello(test.com.company.HelloWorldTest) "expected:<Hello World> but was:<Hell0 World>" [junit]BUILD FAILED E:"projects"sample"build.xml:35: Java returned: -1Total time: 0 seconds
    posted on 2008-02-13 22:54 禮物 閱讀(285) 評論(0)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: www永久免费视频| 好先生在线观看免费播放| 亚洲精品天天影视综合网| 希望影院高清免费观看视频| 亚洲欧美日韩中文无线码 | 国产无遮挡吃胸膜奶免费看| 一本久久免费视频| 久久亚洲AV无码精品色午夜麻豆| 国产成人免费爽爽爽视频| 一级大黄美女免费播放| 亚洲视频在线播放| 日韩精品视频免费网址| 最近中文字幕免费大全| 亚洲黄色激情视频| 亚洲乱码国产乱码精品精| 日韩精品福利片午夜免费观着| 一级毛片a免费播放王色电影| 精品亚洲成a人片在线观看少妇| 国产精品色午夜免费视频| 三年片在线观看免费观看大全动漫| 亚洲色精品VR一区区三区| 亚洲日韩国产精品第一页一区| 成年男女免费视频网站| 91在线视频免费观看| 亚洲中文精品久久久久久不卡| 亚洲综合熟女久久久30p| 午夜免费福利网站| 99久久综合精品免费| a级毛片免费观看网站| 在线观看日本亚洲一区| 亚洲AV无码第一区二区三区| 国产免费一区二区三区VR| 啦啦啦完整版免费视频在线观看 | 午夜亚洲国产理论秋霞| 四虎永久在线精品免费影视| 久久综合国产乱子伦精品免费 | 日本特黄特色AAA大片免费| 亚洲国语在线视频手机在线| 亚洲人成人77777网站| 免费国产成人午夜私人影视| 无码国产精品一区二区免费I6|