第五講單元測試與Junit_第1頁
第五講單元測試與Junit_第2頁
第五講單元測試與Junit_第3頁
第五講單元測試與Junit_第4頁
第五講單元測試與Junit_第5頁
已閱讀5頁,還剩70頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、單元測試單元測試第五講第五講主要內(nèi)容單元測試介紹 單元測試 Quick Start使用JUNIT測試的一些技巧邊界條件MOCK對象簡介單元測試與軟件設(shè)計(jì)1.單元測試介紹 1.1什么是單元測試 單元測試是開發(fā)者寫的一小段代碼,用于檢驗(yàn)被測代碼的一個(gè)很小的、明確的功能是否正確。通常而言,一個(gè)單元測試是用于判斷某個(gè)特定條件下某個(gè)特定的函數(shù)的行為。 執(zhí)行單元測試,是為了證明某段代碼的行為確定和開發(fā)者所期望的一致。1.2單元測試的目的 及早發(fā)現(xiàn)軟件開發(fā)過程中實(shí)現(xiàn)或者設(shè)計(jì)帶來的缺陷 跟蹤詳細(xì)設(shè)計(jì)文檔中設(shè)計(jì)的實(shí)現(xiàn),發(fā)現(xiàn)詳細(xì)設(shè)計(jì)文檔中存在的錯(cuò)誤 驗(yàn)證單元代碼和詳細(xì)設(shè)計(jì)文檔的一致性 發(fā)現(xiàn)在編碼過程中引入的錯(cuò)誤單

2、元測試標(biāo)準(zhǔn)是什么 單元測試標(biāo)準(zhǔn)通常為詳細(xì)設(shè)計(jì)說明書 但是在沒有詳細(xì)設(shè)計(jì)說明書的情況下可以以注釋為測試標(biāo)準(zhǔn)單元測試過程 單元測試計(jì)劃 單元測試設(shè)計(jì) 單元測試實(shí)現(xiàn) 單元測試執(zhí)行 單元測試評估單元測試計(jì)劃 時(shí)間表 工作量 任務(wù)分配 資源安排 測試工具 結(jié)束標(biāo)準(zhǔn) 風(fēng)險(xiǎn)分析 風(fēng)險(xiǎn)應(yīng)對 輸出單元測試計(jì)劃文檔單元測試設(shè)計(jì) 對哪些單元進(jìn)行測試 被測單元的關(guān)系 被測單元與其他模塊的關(guān)系 測試策略選擇 如何設(shè)計(jì)測試用例 如何設(shè)計(jì)單元測試代碼 輸出單元測試用例文檔單元測試實(shí)現(xiàn) 編寫測試用例 編寫測試規(guī)程 測試腳本編寫 測試驅(qū)動(dòng)構(gòu)建 樁構(gòu)建 輸出測試用例 輸出測試規(guī)程 輸出測試代碼和腳本單元測試執(zhí)行 搭建測試環(huán)境 執(zhí)

3、行測試腳本 記錄測試結(jié)果 跟蹤缺陷 回歸測試 輸出單元測試報(bào)告單元測試策略 自頂向下的單元測試 方法 先對最頂層的單元進(jìn)行測試,把頂層單元所調(diào)用的單元做成樁模塊。其次對第二層單元進(jìn)行測試,使用上面已測試的單元做驅(qū)動(dòng)模塊。依次類推直至測試完所有的模塊。 優(yōu)點(diǎn) 可以節(jié)省驅(qū)動(dòng)函數(shù)開發(fā)的工作量,測試效率較高 缺點(diǎn) 隨著被測單元一個(gè)個(gè)的加入,測試過程將變得復(fù)雜,并且開發(fā)和維護(hù)的成本將增加。 自底向上的單元測試 孤立的單元測試 混合的單元測試 自底向上的單元測試 先對最底層的單元進(jìn)行測試,模擬主調(diào)單元構(gòu)建驅(qū)動(dòng)模塊。然后再對上面一層做單元測試,用下面已經(jīng)測試通過的模塊做樁模塊。依次類推,直至測試完所有的模塊

4、。 優(yōu)點(diǎn) 可以節(jié)省樁模塊開發(fā)的工作量,測試效率高 缺點(diǎn) 不是純粹的單元測試,底層函數(shù)的測試質(zhì)量對上層函數(shù)的測試將產(chǎn)生很大的影響。 孤立的單元測試 方法 不考慮模塊和模塊之間的關(guān)系,為每個(gè)模塊設(shè)立樁模塊和驅(qū)動(dòng)模塊。每個(gè)模塊進(jìn)行獨(dú)立的單元測試 優(yōu)點(diǎn) 該策略最簡單,最容易操作??梢赃_(dá)到很高的覆蓋率。似乎純粹的單元測試 缺點(diǎn) 該策略效率很低,需要構(gòu)建大量的驅(qū)動(dòng)和樁 混合的單元測試 自頂向下和自底向上的測試策略綜合了集成的概念,隨著單元測試的進(jìn)行,可以看到系統(tǒng)一個(gè)初步集成的概貌,但是測試覆蓋率會(huì)越來越難保證。并且在每個(gè)單元測試之前必須保證相關(guān)的單元的正確性。孤立的測試策略比較獨(dú)立,覆蓋率容易保證,并且可

5、以并行進(jìn)行,但工作量大。所以采用混合方法比較好。單元測試用例設(shè)計(jì) 單元測試用例設(shè)計(jì)方法 黑盒 白盒 單元測試用例編寫思路 為系統(tǒng)運(yùn)行起來設(shè)計(jì)測試用例 為正向測試設(shè)計(jì)用例 為逆向測試設(shè)計(jì)用例 為滿足特殊需求而設(shè)計(jì)用例 為代碼覆蓋而設(shè)計(jì)測試用例 單元測試用例設(shè)計(jì)五要點(diǎn) 單元接口 局部數(shù)據(jù)結(jié)構(gòu) 獨(dú)立路徑 出錯(cuò)處理 邊界條件 理解需求和設(shè)計(jì) 設(shè)計(jì)測試用例 搭建單元測試環(huán)境 執(zhí)行測試 補(bǔ)充和完善測試用例 分析結(jié)果,給出評價(jià)1.3 我需要做什么呢 它的行為和我的期望一致嗎? 它的行為一直和我的期望一致嗎? 我可以依賴單元測試嗎? 單元測試說明我的意圖了嗎?1.4不寫單元測試的借口 編寫單元測試太花時(shí)間了

6、運(yùn)行測試的時(shí)間太長了 測試代碼并不是我的工作 我并不清楚代碼的行為,所以也就無從測試 但是這些代碼都能編譯通過 公司請我是為了寫代碼,而不是寫單元測試 如果我讓測試員失去工作,我會(huì)覺得內(nèi)疚 公司不會(huì)讓我在真實(shí)系統(tǒng)中運(yùn)行單元測試2.單元測試 Quick Start2.1測試對象尋找數(shù)組中的最大數(shù):public class Largest public static int largest(int list) int index, max=Integer.MAX_VALUE; for (index = 0; index max) max = listindex; return max; 2.2設(shè)計(jì)

7、測試排序測試:【9,7,8】9【7,9,8】9【7,8,9】9重復(fù)值:【7,9,8,9】 9單值:【1】 1負(fù)值:【-9,-8,-7】 -7.空值2.3執(zhí)行測試 執(zhí)行測試并修正錯(cuò)誤 理解單元測試3.使用JUNITJunit簡介Junit的定位Junit的安裝Junit的體系結(jié)構(gòu)Junit的使用3.1構(gòu)建單元測試 TestAccount.java Account.java準(zhǔn)備要測試的條件調(diào)用要測試的方法驗(yàn)證被測試方法的行為是否和結(jié)果一致完成后清理各種資源testCreateAccount()testCreateAccountDef()testCreateAccountDup()createAcc

8、ount()3.2 JUNIT的各種斷言lassertEquals(String message,expected,actual)lassertEquals(String message,expected,actual,tolerance)lassertNull (String message,Object object)lassertNotNull (String message,Object object)lassertSame (String message,expected,actual)lassertNotSame (String message,expected,actual)la

9、ssertTrue (String message,boolean condition)lassertFalse (String message,boolean condition)lfail (String message)l自定義斷言3.3 JUNIT框架import junit.framework.*; /引入測試包public class TestSimple extends TestCase /繼承 TestCase public TestSimple(String name) /默認(rèn)使用父類的實(shí)例化方法 super(name); public void testAdd() /書寫以

10、test開頭的斷言,凡是以test開頭的都會(huì) /被junit自動(dòng)運(yùn)行 assertEquals(2, 1+1); public void testAdds() /一個(gè)測試方法里也可以有多個(gè)斷言 assertEquals(2, 1+1); assertEquals(4, 2+2); assertEquals(-8, -12+4); 測試類也能調(diào)用其他測試類:單獨(dú)的類、包、甚至完整的一個(gè)系統(tǒng)。這可以通過創(chuàng)建test suite來取得。任何測試類都能包含一個(gè)名為suite的靜態(tài)方法: Public static Test suite(); 現(xiàn)假設(shè)有第2個(gè)類TestClassTwo,它使用brute-

11、force算法來尋找旅行銷售商Bob的最短行程。但這個(gè)算法是復(fù)雜度是指數(shù)級的。默認(rèn)情況下你不想包括這些測試。3.4 JUNIT測試的組成(1)import junit.framework.*;public class TestClassTwo extends TestCase public TestClassTwo(String method) super(method); public void testLongRunner() public void testShortTest() public void testAnotherShortTest() public static Test

12、suite() TestSuite suite = new TestSuite(); suite.addTest(new TestClassTwo(“testShortTest”);/裝入測試方法 suite.addTest(new TestClassTwo(testAnotherShortTest); return suite; 3.4 JUNIT測試的組成(2)import junit.framework.*;public class TestClassComposite extends TestCase public TestClassComposite(String method) s

13、uper(method); static public Test suite() TestSuite suite = new TestSuite();/執(zhí)行第一個(gè)測試類所有的測試 suite.addTestSuite(TestClassOne.class); /執(zhí)行第二個(gè)測試類中指定的測試 suite.addTest(TestClassTwo.suite(); return suite; 假設(shè)對于每個(gè)測試,你都需要某種數(shù)據(jù)庫連接,這時(shí),你不需要在每個(gè)測試方法中重復(fù)建立連接和釋放連接了,而只須在setup和teardown方法中分別建立和釋放連接。 執(zhí)行每個(gè)測試方法之前會(huì)執(zhí)行setup,之后會(huì)執(zhí)

14、行teardownJUnit和異常 對測試而言,下面兩種異常我們可能會(huì)感興趣: 從測試代碼拋出的可預(yù)測異常。 由于某個(gè)某塊(或代碼)發(fā)生嚴(yán)重錯(cuò)誤,而拋出的不可預(yù)測異常。 如有一個(gè)名為sortMyList()的方法,如果傳入?yún)?shù)是一個(gè)nulllist,那么我們希望該方法拋出一個(gè)異常。在這種情況下,我們就需要顯式地測試這一點(diǎn)。 assertTure(true)表示“我預(yù)期控制流程會(huì)達(dá)到這個(gè)地方。 Junit可以捕獲任何異常,并且把它報(bào)告為一個(gè)錯(cuò)誤,這些都不需要你的參與。更好的是,Junit不只是讓一個(gè)斷言失敗,而是能夠跟蹤整個(gè)堆棧,并且報(bào)告bug的堆棧調(diào)用順序,當(dāng)你需要查找一個(gè)失敗測試的原因時(shí),這

15、將非常有用。4.測試哪些內(nèi)容測試哪些內(nèi)容4.1測試內(nèi)容(Right-BICEP)Right-結(jié)果是否正確?B-是否所有的邊界條件都是正確的?I-能查一下反向關(guān)聯(lián)嗎?C-能使用其它手段交叉檢查一下結(jié)果嗎?E-你是否可以強(qiáng)制錯(cuò)誤條件發(fā)生?P-是否滿足性能要求? 完全偽造或者不一致的輸入數(shù)據(jù),例如一個(gè)名為“!*w:gjagja;,/.d;”的文件。 格式錯(cuò)誤的數(shù)據(jù),例如沒有頂層域名的電子郵件地址,如fredfoobar 空值或不完整的值 一些與意料中的合理值相去甚遠(yuǎn)的數(shù)值。如一個(gè)歲數(shù)為10000歲。 如果要求的是一個(gè)不允許出現(xiàn)重復(fù)數(shù)值的list,但是傳入的是一個(gè)存在重復(fù)數(shù)值的list如果要求的是一個(gè)

16、有序list,但是傳入的是一個(gè)無序list;或者反之事情到達(dá)的次序是錯(cuò)誤的,或者碰巧和期望的次序不一致,如未登陸系統(tǒng)之前,就嘗試打印文檔。可能的邊界值反向關(guān)聯(lián) 如對結(jié)果進(jìn)行平方的方式來檢查一個(gè)計(jì)算平方根的函數(shù),然后測試結(jié)果是否和原數(shù)據(jù)很接近。 類似地,為了檢查某條記錄是否成功地插入了數(shù)據(jù)庫,你也可以通過查詢這條記錄來驗(yàn)證。其它手段交叉檢查 通常計(jì)算一個(gè)量會(huì)有一種以上的算法。我們可能會(huì)基于運(yùn)行效率或者其他的特性,來選擇算法,那是我們要在產(chǎn)品中使用的,但在測試時(shí)可以使用剩下的算法來做交叉測試。其它手段交叉檢查 另一種辦法,使用類本身不同組成部分的數(shù)據(jù),并且確信它們能“合起來”。如,正在做一個(gè)圖書館

17、的數(shù)據(jù)系統(tǒng)。在這個(gè)系統(tǒng)中,對每一本具體的書,它的數(shù)量永遠(yuǎn)是平衡的。 我們可以用一種數(shù)量檢查另一種數(shù)量。強(qiáng)制產(chǎn)生錯(cuò)誤條件 真實(shí)世界中,錯(cuò)誤總是會(huì)發(fā)生:磁盤會(huì)滿,網(wǎng)絡(luò)連線會(huì)斷開,電子郵件會(huì)多得像掉進(jìn)了黑洞,而程序會(huì)崩潰。你應(yīng)當(dāng)能夠通過強(qiáng)制引發(fā)錯(cuò)誤,來測試你的代碼是如何處理所有這些真實(shí)世界中的問題的。強(qiáng)制產(chǎn)生錯(cuò)誤條件性能問題 不是性能本身 如:“隨著輸入尺寸慢慢變大,問題慢慢變復(fù)雜”的趨勢。 確保性能曲線能夠保持穩(wěn)定5. CORRECT邊界條件5.1 邊界條件o 思考public int calculate(int a,int b)return a/(a+b);5.2 邊界條件o 一致性(Confo

18、rmance)o值是否和預(yù)期的一致o 有序性(Ordering)o值是否如應(yīng)該的那樣,是有序或無序o 區(qū)間性(Range)o值是否位于合理的最小值和最大值之內(nèi)。o 引用,耦合性(Reference)o代碼是否引用了一些不在代碼本身控制范圍之內(nèi)的外部資源5.2 邊界條件o 存在性(Existence):值是否存在o 基數(shù)性(Cardinality)o是否恰好有足夠的值o 時(shí)間性(Time)區(qū)間性 如果數(shù)據(jù)不能像你期望的那樣與結(jié)構(gòu)相一致,將會(huì)出現(xiàn)什么情況?象這種情況,你就需要測試你的結(jié)果并確保其一致性。(一致性) 任何一個(gè)搜索程序都應(yīng)該針對搜索目標(biāo)位于最前或最后的條件做測試。(有序性) 如果這種情

19、況可能發(fā)生,并且在發(fā)生的時(shí)候,你的程序需要處理她,那么你就需要測試這種情況。耦合性 如,網(wǎng)站上一個(gè)用來顯示用戶記錄的方法,可能要求用戶先登錄。 棧的pop()方法要求一個(gè)非空的棧。 給汽車換擋。 前條件、后條件存在性 通過詢問:“給定的事物存在嗎?” 對于你傳入或者維護(hù)的值,先詢問如果值不存在如果它為null、或者等于0,方法的行為將會(huì)怎樣? 面對這些不存在的數(shù)據(jù),java庫的許多方法會(huì)拋出異常。然而要調(diào)試一個(gè)隱藏在庫深處的運(yùn)行期異常通常并不容易。 在期望值不存在的時(shí)候,大多數(shù)方法都會(huì)失敗,但這可能并不是你所期望的結(jié)果。因此,你可以對這些情況進(jìn)行測試,查看當(dāng)網(wǎng)絡(luò)不通、文件不存在的時(shí)候,又會(huì)發(fā)生

20、什么事情。確認(rèn)你的方法處理了“不存在”的情況。 一年中的每一天都是24小時(shí)嗎? 并發(fā)問題練習(xí)(思考棧的測試方法)public interface StackExercise public String pop() throws StackEmptyException; public void push(String item); public String top() throws StackEmptyException; public boolean isEmpty();答案(思考棧的測試方法)o 對于空棧 isEmpty=true,pop(),top(),拋異常。o push(“字符”),

21、top(),返回剛壓入的字符串,isEmpty()=false。o 多次調(diào)用push();驗(yàn)證每一次top()。o push(null),top()=null。o 發(fā)生異常后,棧仍可以使用。6. MOCK對象簡介對象簡介6.1 MOCK對象 概念: MOCK對象是真實(shí)對象在調(diào)試期間的替代品。簡單的替換 一般,我們建議對應(yīng)用程序范圍外的功能調(diào)用進(jìn)行包裝。 因?yàn)楸粶y試代碼只會(huì)通過接口來引用對象,所以它完全不知道它引用的究竟是真實(shí)對象還是mock 對象。 在產(chǎn)品環(huán)境(賣給客戶的真正的代碼)中,當(dāng)初始化這個(gè)類的對象時(shí),傳入的是一個(gè)真實(shí)的systemEnvironment,而另一方面,測試代碼傳入的是則

22、是mockSystemEnvironment。6.2 什么情況下使用MOCK對象o 真實(shí)對象行為不確定(如股票行情)。o 真實(shí)對象很難被創(chuàng)建。o 真實(shí)對象的某些行為很難被觸發(fā)。o 真實(shí)對象令程序的運(yùn)行很慢。o 真實(shí)對象有(或者是)用戶界面。o 測試含有回調(diào)函數(shù)。o 真實(shí)對象并不存在。6.3 使用MOCK對象的步驟o 使用一個(gè)接口來描述這個(gè)對象。o 為產(chǎn)品代碼實(shí)現(xiàn)這個(gè)接口。o 以測試為目的,在MOCK對象中實(shí)現(xiàn)這個(gè)接口。練習(xí):實(shí)現(xiàn)MP3的MOCK對象import java.util.ArrayList;public interface Mp3Player public void play();p

23、ublic void pause();public void stop();public double currentPosition();public String currentSong();public void next();public void prev();public boolean isPlaying();public void loadSongs(ArrayList names);7. 單元測試與軟件設(shè)計(jì)單元測試與軟件設(shè)計(jì)7.1 軟件設(shè)計(jì)關(guān)注的幾個(gè)層面o 通過面向測試的軟件設(shè)計(jì),更好地分離關(guān)注點(diǎn)。o 通過測試驅(qū)動(dòng)的方法,改善接口設(shè)計(jì)。o 確立和局部化驗(yàn)證的責(zé)任。7.2 面向

24、測試的軟件設(shè)計(jì)例:public void sleepUtilNextHour throws InterrupedExceptionint howlong;計(jì)算休眠時(shí)間的一系列代碼Thread.sleep(howlong);Return; 等一個(gè)小時(shí)? 設(shè)一個(gè)計(jì)時(shí)器,調(diào)用這個(gè)函數(shù),等結(jié)束后回來再檢查時(shí)間,如果失敗了,再來處理一下,重新測試?7.3 面向測試的軟件設(shè)計(jì)重構(gòu)代碼public void sleepUtilNextHour throws InterrupedExceptionint howlong=milliSecondsTONextHour(new Date();Thread.sleep(howlong);Return;測試:asserEquals(10000, milli

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論