Sung in Blog

                     一些技術(shù)文章 & 一些生活雜碎
          這篇文章將給你介紹JUnit——一個(gè)工程測(cè)試調(diào)式的工具。 在介紹了了 測(cè)試驅(qū)動(dòng)開發(fā)理論之后,我們繼續(xù)介紹“怎樣用Eclipse創(chuàng)建你的、JUnit Test”。 我們會(huì)用象"hello word"一樣簡(jiǎn)單例子來向你揭露JUnit Case。
            
            自動(dòng)化測(cè)試(automated testing)在好多書籍中被介紹了,但很少注意講怎樣去組織這些測(cè)試。 當(dāng)測(cè)試寫的越多時(shí),很難知道把這些測(cè)試放到哪或者用什么去調(diào)用它們。 在極限編程---Extreme Programming(xp),測(cè)試驅(qū)動(dòng)開發(fā) Test-Driven Development (TDD)盛行的時(shí)代,這成了一個(gè)很大的問題。 你可以把 測(cè)試驅(qū)動(dòng)開發(fā)(TDD)認(rèn)為是"Development through testing" 開發(fā)由經(jīng)測(cè)試。
            
            TDD的主要條款:
            
            在任何代碼片段之前,必須先寫好自動(dòng)檢測(cè)這段代碼功能的程序。既然代碼不存在,那么測(cè)試在一開始就失敗。
            
            在 測(cè)試通過之后,復(fù)制的代碼必須刪掉。
            
            象這樣的方式每個(gè)程序員都可以應(yīng)用,并不需要特定的方法論。但在我們開始寫test之前, 值得我們注意的是,先考慮一下如何組織自動(dòng)化測(cè)試。
            
            這里有幾種我們需要考慮的測(cè)試
            
            單元測(cè)試(Unit test) :這些是為檢查個(gè)別模塊(比如classes類)服務(wù)的。 如果對(duì)象需要訪問外部的數(shù)據(jù)源,比如Database,就需要通過一些模擬的對(duì)象(MOCK object)來模擬Database, (但這也只有在真實(shí)環(huán)境的數(shù)據(jù)與測(cè)試環(huán)境不同的時(shí)候。
            比如測(cè)試環(huán)境里面沒有真實(shí)Datebase,就需要MOCK Object)
            
            用戶測(cè)試 (Customer's test):這里是功能的,系統(tǒng)的并且認(rèn)可的測(cè)試。系統(tǒng)中所有的行為檢查都做為一個(gè)整體。 在XP理論中,這些測(cè)試,是由用戶編寫的,給出測(cè)試案例提綱。
            
            集成測(cè)試 (Itegration tests): 這些測(cè)試象是在用戶測(cè)試和單元測(cè)試之間的十字路口。 集成測(cè)試幫助程序測(cè)試幾個(gè)級(jí)別中交互。 ,Mock Object不會(huì)出現(xiàn)在集承測(cè)試中,他會(huì)增加測(cè)試時(shí)間。同樣,集成測(cè)試也經(jīng)常需要存在的特定的測(cè)試環(huán)境,比如從數(shù)據(jù)庫中放一些測(cè)試數(shù)據(jù)。集成測(cè)試也許使用外部的lib。 Cactus就是這樣一個(gè)J2EE集成的lib。 解釋這些測(cè)試已經(jīng)超出了本篇文章的范圍,并且也需要詳細(xì)的理論敘述,所以,你僅需要知道這種測(cè)試存在就可以了。
            
            開發(fā)測(cè)試(Developer's test) : 這種測(cè)試就是那些開發(fā)者校驗(yàn) 整段代碼,新加的代碼,新加的函數(shù)函數(shù)。 對(duì)于每個(gè)開發(fā)而言, 隨時(shí)生成新的的測(cè)試去檢查代碼是很重要的。 組織這些測(cè)試和組織這些代碼有著同樣的重要性。
            
            至于本文其他地方,只要說到"測(cè)試",就是專指開發(fā)測(cè)試(Developer's test)。
            
            在開發(fā)期間, 一個(gè)程序員有時(shí)可能問自己:系統(tǒng)中這個(gè)行為有test么,這個(gè)test存在么,哪里可以找到這個(gè)test?每次發(fā)現(xiàn)錯(cuò)誤,都是靠最基礎(chǔ)修改bug而不是通過自動(dòng)測(cè)試,這是一個(gè)典型的例子。 在這種情形下事情進(jìn)展可能是:
            
            去找到這個(gè)函數(shù)的測(cè)試(可能測(cè)試已經(jīng)寫了,但里面還有一些小錯(cuò)誤)
            如果這樣的測(cè)試還沒有,或者測(cè)試不能蓋住這種錯(cuò)誤,我們就寫一個(gè)新的測(cè)試來蓋住這種錯(cuò)誤。
            現(xiàn)在 我們深信,程序在新的測(cè)試中不會(huì)通過。
            修復(fù)程序中的bug。
            再運(yùn)行測(cè)試
            確定程序在測(cè)試中通過了。
            
            當(dāng)然,可能出現(xiàn)各種各樣的處理, 但思想必須很明確:你只需糾正那些被測(cè)試找出那些錯(cuò)誤。
            
            現(xiàn)在,讓我們告訴你一個(gè)開發(fā)人員怎樣解決這種情形。 通過存在的功能性的測(cè)試
            
            我利用一些集成的開發(fā)環(huán)境(IDE)來查找 被修正那些類和方法的放在什么地方。
            
            制造一個(gè)已知的錯(cuò)誤環(huán)境,來查找那些代碼判斷存在錯(cuò)誤。
            
            最后但不是最不重要的,寫好測(cè)試并且放到一個(gè)現(xiàn)有的測(cè)試類中去。 如果你不小心出了錯(cuò)誤, 期望你和你的同事能注意到副本,并且糾正它
            
            都準(zhǔn)就緒,開始建立測(cè)試了, 所以現(xiàn)在需要給測(cè)試取一個(gè)名稱。 你可能說,“這不是問題: 在每個(gè)類面前加個(gè)Test就是了!” 但并不是那么簡(jiǎn)單的, 讓我告訴你這樣如果可能造成的問題:
            
            當(dāng)時(shí)候我們?cè)谑褂肨DD的方式開發(fā)時(shí), 需要測(cè)試的class或者method可能都不存在。
            
            也可能一個(gè)test 含蓋了好幾個(gè)方法,甚至好幾個(gè)classes。
            
            這些僅僅是最普通的問題, 下面還有更多。
            
            給個(gè)在test命名上的建議: test 類的取名首先應(yīng)該表達(dá)出這個(gè)類是一個(gè)test類,并且能確切的表示出他要檢查哪些,留有這個(gè)原class名的味道。 其實(shí)這很容易,請(qǐng)別擔(dān)心這個(gè)名稱會(huì)變的很長(zhǎng)或者很丑陋,自己隨便怎樣取都可以。
            
            下面我們將使用Eclipse中的JUnit工具建立我們的第一個(gè)測(cè)試,假定你已經(jīng)下載了這個(gè)產(chǎn)品的當(dāng)前版本, 如果沒有,你隨時(shí)可以從它的官方網(wǎng)站(www.eclipse.org)下載。我們需要JUnit,你也可以從它的官方網(wǎng)站(www.junit.org)上下載,下載并解壓縮到你硬盤中存放java libaries的地方。
            
            打開Eclipse.我們將建立一個(gè)新的工程的工作空間(workplace project) 點(diǎn) File -> New ->Project,選擇Java一路Next。 輸入工程名稱(project name),比如ProjectWithJUnit. 點(diǎn)擊完成。 這樣就建立了一個(gè)新工程,讓我們配置一下我們的Eclipse,于是,我們把JUnit library 添加到build path. 點(diǎn)擊 Project-->Properties, 選擇Java Build Path Libraries, 點(diǎn)Add Exteranal JARs 選中JUnit.jar。 你將會(huì)看到JUnit將會(huì)出現(xiàn)在的屏幕上 libraries列表中。 點(diǎn)Okay,Eclipse將強(qiáng)制rebuild所有的build paths.
            
            我們已經(jīng)準(zhǔn)備好,開始寫我們的"Hello World"了 . 讓我們遵照TDD規(guī)范:在編碼之前就建立測(cè)試。為了, 我們將假頂我們將要寫的類名是HelloWorld 有一個(gè)返回字符串的方法 say().
            
            要建立這樣一個(gè)test, 在ProjectWithJUnit標(biāo)題上右鍵, 選擇New -> Other,展開"Java", 選擇JUnit. 在對(duì)話框的右邊一攔里選擇TestCase,接著點(diǎn)Next. 參見圖1。
            
            
           

            圖1。 在Eclipse 中建立JUnit test
            在Test class:一攔里輸入我們需要測(cè)試的class--HelloWorld。并且給Test case取個(gè)名稱--- 比如,TestThatWeGetHelloWorldPrompt(是的,這看上去太長(zhǎng)了,但是它能很清楚表達(dá)出它的意思) 點(diǎn)Finish完成。
            
            下面是 TestThatWeGetHelloWorldPrompt.java的代碼:
            
            public class TestThatWeGetHelloWorldPrompt
            
            extends TestCase {
            
            public TestThatWeGetHelloWorldPrompt(
            
            String name) {
            
            super(name);
            
            }
            
            public void testSay() {
            
            HelloWorld hi = new HelloWorld();
            
            assertEquals("Hello World!", hi.say());
            
            }
            
            public static void main(String[] args) {
            
            junit.textui.TestRunner.run(
            
            TestThatWeGetHelloWorldPrompt.class);
            
            }
            
            }
            
            這個(gè)代碼一點(diǎn)都不復(fù)雜,僅僅有一點(diǎn)點(diǎn)特別。 不管怎樣,讓我們?cè)敿?xì)的檢查它。 我們繼承了JUnit的TestCase. (TestCase 在JUnit的javadoc里定義是"用來運(yùn)行多個(gè)Test的固定裝置")。 JUnit也定義了TestSuite 由于一組關(guān)聯(lián)的TestCase組成..
            
            通過以下兩步來建立我們簡(jiǎn)單的Test Case;
            
            建立Junit.framework.TestCase的實(shí)例.
            定義一些 以"test"開頭的測(cè)試函數(shù), 并且返回一空值.(比如 testWasTranscationSuccessful(),testShow()等等).
            
            TestThatWeGetHelloWorldPrompt.java 同時(shí)遵循這些標(biāo)準(zhǔn): 這些TestCase的子類含有一個(gè)testSay()的方法. 這個(gè)方法由assertEquals()方法調(diào)用, 用于檢驗(yàn)say()的返回值(按照這里的做法返回應(yīng)該是不一致,因?yàn)橐婚_始建立的HelloWorld 我們讓say()返回的值是null).
            
            main()主函數(shù)是用來運(yùn)行test并且顯示輸出的結(jié)果. JUnit的TestRunnery以(swing.u)圖形和本文(text.ui)的的方式來執(zhí)行我們的test并反饋信息。我們就使用文本(text.ui),這個(gè)Eclipse肯定支持. (譯注:這里可能翻譯的不怎么好,所謂文本和圖形,是指你在建立TestCase的時(shí)候,有一個(gè)選項(xiàng),Which method stubs would you like to create,選擇text.ui|| swing.ui||awt.ui,一般是選擇text.ui因?yàn)镋clipse肯定支持這個(gè)), 依照這些文本的信息,Eclipse同時(shí)會(huì)生成圖形顯示。(在Package Exploer的下面Tab條上會(huì)多個(gè)JUnit,點(diǎn)它就看到了:)。
            
            又一個(gè)所以,按照現(xiàn)在這樣測(cè)試驅(qū)動(dòng)的開發(fā)的做法, 一旦我們跑起了我們的test,我們應(yīng)該看到返回一些錯(cuò)誤的信息。 點(diǎn)Run-> Run as -> JUnit Test(注意啊, 這個(gè)TestThatWeGetHelloWorldPrompt.java應(yīng)該在Package Explorer被點(diǎn)中,在左邊那個(gè)window中),你點(diǎn)到的因該是JUnit window(就是下面的那個(gè)Tab條,注意不是Package Exploer),這樣你就看到了JUnit window, 他會(huì)顯示一個(gè)紅色條,表示是一個(gè)失敗的Test。 (如果你按了運(yùn)行它沒有自動(dòng)轉(zhuǎn)到這個(gè)窗口,你可以點(diǎn)做下Tab條 上的JUnit標(biāo)簽。)
            
           

            一按運(yùn)行, 太好了,果然出錯(cuò)了。好,現(xiàn)在正式開始建立用于工作的HelloWorld代碼,---點(diǎn)New->Class,可能和原來的的重復(fù),那就把原來的刪掉。代碼如下:
            
            HelloWolrd.java
            
            public class HelloWorld {
            
            public String say() {
            
            return("Hello World!");
            
            }
            
            }
            
            這及為簡(jiǎn)單的,都用不著注釋。現(xiàn)在再來測(cè)試一下看看結(jié)果。就用上面的方法,點(diǎn)Run-> Run As Jnit. 在左邊的JUnit窗口中出現(xiàn)了一個(gè)綠條。 看圖三。 出現(xiàn)綠色的條表示測(cè)試通過了。
            
            
           

            現(xiàn)在,再變個(gè)條件,讓測(cè)試不通過。 這將幫助我們理解JUnit test怎樣覆蓋并且報(bào)出不同的錯(cuò)誤。 編輯 assertEquals()方法,把它的返回值從"Hello World!"變成另外一個(gè)值 比如"Hello ME!". 這樣,當(dāng)你再運(yùn)行這個(gè)JUnit test,那個(gè)顯示條又變成紅的了,并且在Failuer Trace里看到是不是什么導(dǎo)致了錯(cuò)誤。 如圖:
            
            

            總結(jié)。我想說一些自己的想法(這里還是原文不是翻譯過來的)。 我過去并不認(rèn)為測(cè)試代碼是開發(fā)過程中很重要的一部分。 但在最近幾年發(fā)展的很快,多虧了那些方法論(比如基于異常開發(fā)"exceptions-based development"等),他們促進(jìn)了測(cè)試以及測(cè)試工具的發(fā)展。
          posted on 2005-11-02 15:19 Sung 閱讀(261) 評(píng)論(0)  編輯  收藏 所屬分類: Eclipse
          主站蜘蛛池模板: 吴江市| 台山市| 邯郸市| 晋州市| 惠来县| 惠水县| 盘锦市| 唐山市| 新源县| 乌审旗| 铁岭市| 西贡区| 武鸣县| 霞浦县| 墨玉县| 双峰县| 交城县| 武宣县| 衡水市| 大新县| 若羌县| 章丘市| 南江县| 襄垣县| 耒阳市| 房山区| 集安市| 聂荣县| 宁晋县| 武平县| 台山市| 安顺市| 新源县| 镇宁| 和硕县| 贡嘎县| 惠东县| 弋阳县| 和龙市| 汉沽区| 昭觉县|