楊鵬
摘要:軟件測(cè)試技術(shù)在軟件質(zhì)量控制過(guò)程中一直起著非常重要的作用。JUnit是被廣泛應(yīng)用的Java單元測(cè)試框架,主要測(cè)試基于java語(yǔ)言編寫的程序代碼,用于編寫和運(yùn)行可重復(fù)的測(cè)試。Feed4JUnit是開(kāi)源的基于JUnit的擴(kuò)展,通過(guò)使用Feed4JUnit提供的注釋,用戶可以很方便地把測(cè)試數(shù)據(jù)存放在文件或其他數(shù)據(jù)源。本文分析了應(yīng)用Feed4JUnit進(jìn)行單元測(cè)試的方法,并通過(guò)實(shí)際開(kāi)發(fā)示例實(shí)現(xiàn)數(shù)據(jù)與代碼分離的測(cè)試。
關(guān)鍵詞:Feed4JUnit架構(gòu);單元測(cè)試;數(shù)據(jù)源
中圖分類號(hào):TP311.52 文獻(xiàn)標(biāo)識(shí)碼:A
Research on Unit Testing Technology Based on Feed4JUnit Architecture
YANG Peng
(School of Information Engineering Guangzhou Panyu Polytechnic,Guangzhou 511483,China)
Abstract:Software testing technology has been under the control of software processto use is very important.Unit is the Java unit test framework is widely used,mainly used for testing the class and method based on the Java language,Feed4JUnit is the extension of JUnit based on open source, using the Feed4JUnit annotation,the usercan be very convenient to test the data stored in a file or other data source.This paperanalyzes the application of Feed4JUnit unit test methods,and through the actualexample of developing,realize the separation of data and code test.
Keywords:Feed4JUnit;unit test;data source
1 引言(Introduction)
單元測(cè)試(Unit Testing),是指對(duì)軟件中的最小可測(cè)試單元進(jìn)行檢查和驗(yàn)證。對(duì)于單元測(cè)試中單元的含義,一般來(lái)說(shuō),要根據(jù)實(shí)際情況去判定其具體含義,如C語(yǔ)言中單元指一個(gè)函數(shù)[1],Java里單元指一個(gè)類,圖形化的軟件中可以指一個(gè)窗口或一個(gè)菜單等??偟膩?lái)說(shuō),單元就是人為規(guī)定的最小的被測(cè)功能模塊[2]。單元測(cè)試是在軟件開(kāi)發(fā)過(guò)程中要進(jìn)行的最低級(jí)別的測(cè)試活動(dòng),軟件的獨(dú)立單元將在與程序的其他部分相隔離的情況下進(jìn)行測(cè)試[3]。單元測(cè)試不僅僅保證代碼在方法級(jí)別的正確性,它還能改進(jìn)設(shè)計(jì),易于對(duì)代碼重構(gòu)[4]。凡是容易編寫單元測(cè)試的代碼,往往是優(yōu)秀的設(shè)計(jì)和松耦合的組件,凡是難于編寫單元測(cè)試的代碼,往往是設(shè)計(jì)不佳和耦合度高的系統(tǒng)[5]。因此,編寫單元測(cè)試不僅僅是掌握單元測(cè)試柜架的用法,更重要的是在編寫單元測(cè)試的過(guò)程中發(fā)現(xiàn)設(shè)計(jì)缺陷,改進(jìn)系統(tǒng)結(jié)構(gòu),從而實(shí)現(xiàn)良好的可擴(kuò)展性。
任何一個(gè)項(xiàng)目,單元測(cè)試應(yīng)該在詳細(xì)設(shè)計(jì)之后開(kāi)始進(jìn)行,首先根據(jù)詳細(xì)設(shè)計(jì)文檔進(jìn)行單元測(cè)試用例的編寫,編寫完成后進(jìn)行代碼開(kāi)發(fā),代碼完成后運(yùn)行單元測(cè)試,如果通過(guò),則該方法可以發(fā)布運(yùn)行,如果不通過(guò)需要進(jìn)行代碼改造,再進(jìn)行單元測(cè)試,直到單元測(cè)試運(yùn)行通過(guò)為止。
2 Junit單元測(cè)試架構(gòu)(Junit unit test framework)
JUnit是由Erich Gamma和Kent Beck編寫的一個(gè)回歸測(cè)試框架(Regression Testing Framework)。Junit測(cè)試是程序員測(cè)試,即所謂白盒測(cè)試,因?yàn)槌绦騿T知道被測(cè)試的軟件如何(How)完成功能和完成什么樣(What)的功能。Junit是一套框架,繼承TestCase類,就可以用Junit進(jìn)行自動(dòng)測(cè)試了。通常來(lái)說(shuō),在極限編程中,基本過(guò)程是這樣的:構(gòu)思→編寫測(cè)試代碼→編寫代碼→測(cè)試,而且編寫測(cè)試和編寫代碼都是增量式的,寫一點(diǎn)測(cè)一點(diǎn),在編寫以后的代碼中如果發(fā)現(xiàn)問(wèn)題可以較快的追蹤到問(wèn)題的原因,減小回歸錯(cuò)誤的糾錯(cuò)難度,如圖1所示的是Junit基本架構(gòu)。
圖1 Junit基本架構(gòu)
Fig.1 The basic architecture of Junit
在Junit類中,有很多定義類。Test:是TestCase、TestSuite的共同接口。run(TestResult)用來(lái)運(yùn)行Test,并且將結(jié)果保存到TestResult。TestCase:Test的接口的抽象實(shí)現(xiàn),是Abstract類,所以不能實(shí)例化,能被繼承。其中一個(gè)構(gòu)造函數(shù)TestCase(String Name),根據(jù)輸入的參數(shù),創(chuàng)建一個(gè)測(cè)試實(shí)例。參數(shù)為該類的以test開(kāi)頭的方法名,把它添加到TestSuite中,指定僅僅運(yùn)行TestCase中的一個(gè)方法。
TestSuite:實(shí)現(xiàn)Test接口??梢越M裝一個(gè)或者多個(gè)TestCase。待測(cè)試類中可能包括了對(duì)被測(cè)類的多個(gè)TestCase,而TestSuit可以保存多個(gè)TestCase,負(fù)責(zé)收集這些測(cè)試,這樣就可以一個(gè)Suite就能運(yùn)行對(duì)被測(cè)類的多個(gè)測(cè)試。TestResult:保存TestCase運(yùn)行中的事件。TestResult有List
ResultPrinter:實(shí)現(xiàn)TestListener接口。在TestCase運(yùn)行過(guò)程中,對(duì)所監(jiān)聽(tīng)的對(duì)象的事件以一定格式及時(shí)輸出,運(yùn)行完后,對(duì)TestResult對(duì)象進(jìn)行分析,輸出的統(tǒng)計(jì)結(jié)果。BaseTestRunner:所有TestRunner的超類。java Junit.swingui.TestRunner:實(shí)BaseTestRunner,提供圖形界面。java Junit.textui.TestRunner:實(shí)現(xiàn)BaseTestRunner,提供文本界面。下面將以它做為例子講解JUnit生命周期。
3 JUnit4測(cè)試實(shí)例(JUnit4 test examples)
在應(yīng)用程序的業(yè)務(wù)邏輯中存在大量的這樣的接口:他們接受不同的輸入,然后進(jìn)行或驗(yàn)證、或處理,進(jìn)而完成相同的流程。比如網(wǎng)站的登錄入口,用戶名和密碼都有長(zhǎng)度的限制,同時(shí)也具有是否允許特殊字符的限制等,所以在我們進(jìn)行其單元測(cè)試的過(guò)程中,根據(jù)不同長(zhǎng)度的用戶名和密碼,以及不同的字符組合,只需要提供相同的測(cè)試代碼結(jié)構(gòu),就能完成測(cè)試,不同的僅僅測(cè)試數(shù)據(jù)與期望值,但是因?yàn)槊恳粋€(gè)測(cè)試方法中的輸入?yún)?shù)不同,我們必須為每一個(gè)輸入組編寫單獨(dú)的測(cè)試用例,從而產(chǎn)生大量冗余代碼,十分不便于維護(hù)。
將Java對(duì)象名稱(每個(gè)單詞的頭字母大寫)按照數(shù)據(jù)庫(kù)命名的習(xí)慣進(jìn)行格式化,格式化后的數(shù)據(jù)為小寫字母,并且使用下劃線分割命名單詞,要求對(duì)輸入數(shù)據(jù)進(jìn)行非法驗(yàn)證。
首先新建一個(gè)TestJUnit。打開(kāi)項(xiàng)目TestJUnit的屬性頁(yè)→選擇“Java Build Path”子選項(xiàng)→點(diǎn)選“Add Library…”按鈕→在彈出的“Add Library”對(duì)話框中選擇JUnit(圖2),并在下一頁(yè)中選擇版本4.1后點(diǎn)擊“Finish”按鈕。
圖2 JUnit 運(yùn)行測(cè)試界面
Fig.2 JUnit run the test interface
在JUnit運(yùn)行界面提示有兩個(gè)測(cè)試情況未通過(guò),當(dāng)首字母大寫時(shí)得到的處理結(jié)果與預(yù)期的有偏差,造成測(cè)試失?。欢?dāng)測(cè)試對(duì) null的處理結(jié)果時(shí),則直接拋出了異常,測(cè)試錯(cuò)誤。
JUnit將測(cè)試失敗的情況分為兩種:failure和error。Failure一般由單元測(cè)試使用的斷言方法判斷失敗引起,它表示在測(cè)試點(diǎn)發(fā)現(xiàn)了問(wèn)題;而error則是由代碼異常引起,這是測(cè)試目的之外的發(fā)現(xiàn),它可能產(chǎn)生于測(cè)試代碼本身的錯(cuò)誤(測(cè)試代碼也是代碼,同樣無(wú)法保證完全沒(méi)有缺陷),也可能是被測(cè)試代碼中的一個(gè)隱藏的bug。顯然,被測(cè)試代碼中并沒(méi)有對(duì)首字母大寫和null這兩種特殊情況進(jìn)行處理,現(xiàn)在對(duì)源代碼進(jìn)行修改,添加對(duì)這兩種情況的處理,代碼如下:
package sample.test;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import sample.code.UserAccess;
/*
* JUnit - Parameter test sample
*/
@RunWith(Parameterized.class)
public class JunitSample {
private String user;
private String pw;
private boolean expected;
@Parameters
public static Collection dataGenerater() {
return Arrays.asList(new Object[][] {
{ "user01", "123456", true },
{ "helloworld", "123456", false },
{ "david", "re*ads", false },
{ "goodone", "onegood", true } });
}
public JunitSample(String user, String pw, boolean expected) {
this.user = user;
this.pw = pw;
this.expected = expected;
}
@Test
public void testAccessCheck() {
assertEquals(expected, UserAccess.accessCheck(user, pw));
}
}
運(yùn)行測(cè)試,顯示的測(cè)試結(jié)果如圖3所示。
圖3 測(cè)試結(jié)果
Fig.3 The test results
通過(guò)以上代碼可以看出,JUnit4通過(guò)使用一個(gè)標(biāo)記@Parameters注釋的返回類型為Collection的靜態(tài)方法產(chǎn)生數(shù)據(jù),測(cè)試數(shù)據(jù)通過(guò)變量傳遞給測(cè)試方法,從而完成多數(shù)據(jù)輸入的測(cè)試。但是隨著業(yè)務(wù)的需要,測(cè)試人員需要經(jīng)常增加測(cè)試數(shù)據(jù)與修改現(xiàn)有測(cè)試數(shù)據(jù),JUnit4提供的硬編碼方式已經(jīng)愈顯笨重和不便,數(shù)據(jù)與代碼分離顯得尤為重要。
本文所述的Feed4Junit可以良好 地解決數(shù)據(jù)與代碼分離的問(wèn)題,F(xiàn)eed4JUnit是JUnit測(cè)試框架的擴(kuò)展,它通過(guò)操作來(lái)自于文件以及不同的數(shù)據(jù)源的測(cè)試數(shù)據(jù),使單元測(cè)試變得更容易編寫與維護(hù)。本文通過(guò)實(shí)例展示Feed4JUnit的安裝以及測(cè)試代碼與數(shù)據(jù)分離的實(shí)現(xiàn),本文的實(shí)例代碼全部基于針對(duì)如下一個(gè)簡(jiǎn)單的用戶登錄檢驗(yàn)的類。
package sample.code;
public class UserAccess {
// simple validation for user name and password
public static boolean accessCheck(String userName, String password) {
if (userName.length() <= 4 || userName.length() > 8)
return false;
if (password.length() <= 4 || password.length() > 8)
return false;
if (userName.contains("@"))
return false;
if (password.contains("*"))
return false;
return true;
}
}
在靜態(tài)方法excel中,本文采用二維數(shù)組的方式來(lái)構(gòu)建測(cè)試所需要的參數(shù)列表,其中每個(gè)數(shù)組中的元素的放置順序并沒(méi)有什么要求,只要和構(gòu)造函數(shù)中的順序保持一致就可以了?,F(xiàn)在如果再增加一種測(cè)試情況,只需要在靜態(tài)方法excel中添加相應(yīng)的數(shù)組即可,不再需要復(fù)制粘貼出一個(gè)新的方法出來(lái)了。
隨著項(xiàng)目的進(jìn)展,項(xiàng)目的規(guī)模在不斷地膨脹,為了保證項(xiàng)目的質(zhì)量,有計(jì)劃的執(zhí)行全面的單元測(cè)試是非常有必要的。但單靠JUnit提供的測(cè)試套件很難勝任這項(xiàng)工作,因?yàn)轫?xiàng)目中單元測(cè)試類的個(gè)數(shù)在不停的增加,測(cè)試套件卻無(wú)法動(dòng)態(tài)的識(shí)別新加入的單元測(cè)試類,需要手動(dòng)修改測(cè)試套件。
4 結(jié)論(Conclusion)
本文主要介紹了Junit相關(guān)單元測(cè)試技術(shù),分析了應(yīng)用Feed4JUnit進(jìn)行單元測(cè)試的方法,用戶可以方便的把測(cè)試數(shù)據(jù)存放在文件或其它數(shù)據(jù)源。通過(guò)提供簡(jiǎn)單的注釋,F(xiàn)eed4JUnit使用戶能夠極其方便的實(shí)施數(shù)據(jù)與代碼分離的測(cè)試,極大地增強(qiáng)了JUnit測(cè)試框架的易用性。本文所敘述的僅僅是Feed4JUnit提供的測(cè)試增強(qiáng)功能的一部分,Junit4同時(shí)還提供了大量數(shù)據(jù)的隨機(jī)測(cè)試和等價(jià)類測(cè)試等眾多功能。
參考文獻(xiàn)(References)
[1] 高共革,楊靜.基于.NET的單元測(cè)試自動(dòng)化方法研究[J].微計(jì)算機(jī)信息,2008,24(19):280-281.
[2] 吳高峽,王芙蓉.單元測(cè)試的自動(dòng)化實(shí)踐[J].計(jì)算機(jī)與數(shù)字工程,2007,35(1):174-176.
[3] 吳繼娟,孫媛媛,劉桂艷.基于BIST的FPGA邏輯單元測(cè)試方法[J].哈爾濱工業(yè)大學(xué)學(xué)報(bào),2004,36(8):1074-1076.
[4] 嚴(yán)俊,等.JUTA:一個(gè)Java自動(dòng)化單元測(cè)試工具[J].計(jì)算機(jī)研究與發(fā)展,2010(10):1840-1848.
[5] 張巍,尹海波,孫立財(cái).軟件的單元測(cè)試方法[J].光電技術(shù)應(yīng)用,2006,21(2):36-38.
作者簡(jiǎn)介:
楊 鵬(1978-),女,碩士,講師.研究領(lǐng)域:數(shù)據(jù)挖掘,圖形圖像處理,軟件測(cè)試.
endprint
將Java對(duì)象名稱(每個(gè)單詞的頭字母大寫)按照數(shù)據(jù)庫(kù)命名的習(xí)慣進(jìn)行格式化,格式化后的數(shù)據(jù)為小寫字母,并且使用下劃線分割命名單詞,要求對(duì)輸入數(shù)據(jù)進(jìn)行非法驗(yàn)證。
首先新建一個(gè)TestJUnit。打開(kāi)項(xiàng)目TestJUnit的屬性頁(yè)→選擇“Java Build Path”子選項(xiàng)→點(diǎn)選“Add Library…”按鈕→在彈出的“Add Library”對(duì)話框中選擇JUnit(圖2),并在下一頁(yè)中選擇版本4.1后點(diǎn)擊“Finish”按鈕。
圖2 JUnit 運(yùn)行測(cè)試界面
Fig.2 JUnit run the test interface
在JUnit運(yùn)行界面提示有兩個(gè)測(cè)試情況未通過(guò),當(dāng)首字母大寫時(shí)得到的處理結(jié)果與預(yù)期的有偏差,造成測(cè)試失敗;而當(dāng)測(cè)試對(duì) null的處理結(jié)果時(shí),則直接拋出了異常,測(cè)試錯(cuò)誤。
JUnit將測(cè)試失敗的情況分為兩種:failure和error。Failure一般由單元測(cè)試使用的斷言方法判斷失敗引起,它表示在測(cè)試點(diǎn)發(fā)現(xiàn)了問(wèn)題;而error則是由代碼異常引起,這是測(cè)試目的之外的發(fā)現(xiàn),它可能產(chǎn)生于測(cè)試代碼本身的錯(cuò)誤(測(cè)試代碼也是代碼,同樣無(wú)法保證完全沒(méi)有缺陷),也可能是被測(cè)試代碼中的一個(gè)隱藏的bug。顯然,被測(cè)試代碼中并沒(méi)有對(duì)首字母大寫和null這兩種特殊情況進(jìn)行處理,現(xiàn)在對(duì)源代碼進(jìn)行修改,添加對(duì)這兩種情況的處理,代碼如下:
package sample.test;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import sample.code.UserAccess;
/*
* JUnit - Parameter test sample
*/
@RunWith(Parameterized.class)
public class JunitSample {
private String user;
private String pw;
private boolean expected;
@Parameters
public static Collection dataGenerater() {
return Arrays.asList(new Object[][] {
{ "user01", "123456", true },
{ "helloworld", "123456", false },
{ "david", "re*ads", false },
{ "goodone", "onegood", true } });
}
public JunitSample(String user, String pw, boolean expected) {
this.user = user;
this.pw = pw;
this.expected = expected;
}
@Test
public void testAccessCheck() {
assertEquals(expected, UserAccess.accessCheck(user, pw));
}
}
運(yùn)行測(cè)試,顯示的測(cè)試結(jié)果如圖3所示。
圖3 測(cè)試結(jié)果
Fig.3 The test results
通過(guò)以上代碼可以看出,JUnit4通過(guò)使用一個(gè)標(biāo)記@Parameters注釋的返回類型為Collection的靜態(tài)方法產(chǎn)生數(shù)據(jù),測(cè)試數(shù)據(jù)通過(guò)變量傳遞給測(cè)試方法,從而完成多數(shù)據(jù)輸入的測(cè)試。但是隨著業(yè)務(wù)的需要,測(cè)試人員需要經(jīng)常增加測(cè)試數(shù)據(jù)與修改現(xiàn)有測(cè)試數(shù)據(jù),JUnit4提供的硬編碼方式已經(jīng)愈顯笨重和不便,數(shù)據(jù)與代碼分離顯得尤為重要。
本文所述的Feed4Junit可以良好 地解決數(shù)據(jù)與代碼分離的問(wèn)題,F(xiàn)eed4JUnit是JUnit測(cè)試框架的擴(kuò)展,它通過(guò)操作來(lái)自于文件以及不同的數(shù)據(jù)源的測(cè)試數(shù)據(jù),使單元測(cè)試變得更容易編寫與維護(hù)。本文通過(guò)實(shí)例展示Feed4JUnit的安裝以及測(cè)試代碼與數(shù)據(jù)分離的實(shí)現(xiàn),本文的實(shí)例代碼全部基于針對(duì)如下一個(gè)簡(jiǎn)單的用戶登錄檢驗(yàn)的類。
package sample.code;
public class UserAccess {
// simple validation for user name and password
public static boolean accessCheck(String userName, String password) {
if (userName.length() <= 4 || userName.length() > 8)
return false;
if (password.length() <= 4 || password.length() > 8)
return false;
if (userName.contains("@"))
return false;
if (password.contains("*"))
return false;
return true;
}
}
在靜態(tài)方法excel中,本文采用二維數(shù)組的方式來(lái)構(gòu)建測(cè)試所需要的參數(shù)列表,其中每個(gè)數(shù)組中的元素的放置順序并沒(méi)有什么要求,只要和構(gòu)造函數(shù)中的順序保持一致就可以了?,F(xiàn)在如果再增加一種測(cè)試情況,只需要在靜態(tài)方法excel中添加相應(yīng)的數(shù)組即可,不再需要復(fù)制粘貼出一個(gè)新的方法出來(lái)了。
隨著項(xiàng)目的進(jìn)展,項(xiàng)目的規(guī)模在不斷地膨脹,為了保證項(xiàng)目的質(zhì)量,有計(jì)劃的執(zhí)行全面的單元測(cè)試是非常有必要的。但單靠JUnit提供的測(cè)試套件很難勝任這項(xiàng)工作,因?yàn)轫?xiàng)目中單元測(cè)試類的個(gè)數(shù)在不停的增加,測(cè)試套件卻無(wú)法動(dòng)態(tài)的識(shí)別新加入的單元測(cè)試類,需要手動(dòng)修改測(cè)試套件。
4 結(jié)論(Conclusion)
本文主要介紹了Junit相關(guān)單元測(cè)試技術(shù),分析了應(yīng)用Feed4JUnit進(jìn)行單元測(cè)試的方法,用戶可以方便的把測(cè)試數(shù)據(jù)存放在文件或其它數(shù)據(jù)源。通過(guò)提供簡(jiǎn)單的注釋,F(xiàn)eed4JUnit使用戶能夠極其方便的實(shí)施數(shù)據(jù)與代碼分離的測(cè)試,極大地增強(qiáng)了JUnit測(cè)試框架的易用性。本文所敘述的僅僅是Feed4JUnit提供的測(cè)試增強(qiáng)功能的一部分,Junit4同時(shí)還提供了大量數(shù)據(jù)的隨機(jī)測(cè)試和等價(jià)類測(cè)試等眾多功能。
參考文獻(xiàn)(References)
[1] 高共革,楊靜.基于.NET的單元測(cè)試自動(dòng)化方法研究[J].微計(jì)算機(jī)信息,2008,24(19):280-281.
[2] 吳高峽,王芙蓉.單元測(cè)試的自動(dòng)化實(shí)踐[J].計(jì)算機(jī)與數(shù)字工程,2007,35(1):174-176.
[3] 吳繼娟,孫媛媛,劉桂艷.基于BIST的FPGA邏輯單元測(cè)試方法[J].哈爾濱工業(yè)大學(xué)學(xué)報(bào),2004,36(8):1074-1076.
[4] 嚴(yán)俊,等.JUTA:一個(gè)Java自動(dòng)化單元測(cè)試工具[J].計(jì)算機(jī)研究與發(fā)展,2010(10):1840-1848.
[5] 張巍,尹海波,孫立財(cái).軟件的單元測(cè)試方法[J].光電技術(shù)應(yīng)用,2006,21(2):36-38.
作者簡(jiǎn)介:
楊 鵬(1978-),女,碩士,講師.研究領(lǐng)域:數(shù)據(jù)挖掘,圖形圖像處理,軟件測(cè)試.
endprint
將Java對(duì)象名稱(每個(gè)單詞的頭字母大寫)按照數(shù)據(jù)庫(kù)命名的習(xí)慣進(jìn)行格式化,格式化后的數(shù)據(jù)為小寫字母,并且使用下劃線分割命名單詞,要求對(duì)輸入數(shù)據(jù)進(jìn)行非法驗(yàn)證。
首先新建一個(gè)TestJUnit。打開(kāi)項(xiàng)目TestJUnit的屬性頁(yè)→選擇“Java Build Path”子選項(xiàng)→點(diǎn)選“Add Library…”按鈕→在彈出的“Add Library”對(duì)話框中選擇JUnit(圖2),并在下一頁(yè)中選擇版本4.1后點(diǎn)擊“Finish”按鈕。
圖2 JUnit 運(yùn)行測(cè)試界面
Fig.2 JUnit run the test interface
在JUnit運(yùn)行界面提示有兩個(gè)測(cè)試情況未通過(guò),當(dāng)首字母大寫時(shí)得到的處理結(jié)果與預(yù)期的有偏差,造成測(cè)試失?。欢?dāng)測(cè)試對(duì) null的處理結(jié)果時(shí),則直接拋出了異常,測(cè)試錯(cuò)誤。
JUnit將測(cè)試失敗的情況分為兩種:failure和error。Failure一般由單元測(cè)試使用的斷言方法判斷失敗引起,它表示在測(cè)試點(diǎn)發(fā)現(xiàn)了問(wèn)題;而error則是由代碼異常引起,這是測(cè)試目的之外的發(fā)現(xiàn),它可能產(chǎn)生于測(cè)試代碼本身的錯(cuò)誤(測(cè)試代碼也是代碼,同樣無(wú)法保證完全沒(méi)有缺陷),也可能是被測(cè)試代碼中的一個(gè)隱藏的bug。顯然,被測(cè)試代碼中并沒(méi)有對(duì)首字母大寫和null這兩種特殊情況進(jìn)行處理,現(xiàn)在對(duì)源代碼進(jìn)行修改,添加對(duì)這兩種情況的處理,代碼如下:
package sample.test;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import sample.code.UserAccess;
/*
* JUnit - Parameter test sample
*/
@RunWith(Parameterized.class)
public class JunitSample {
private String user;
private String pw;
private boolean expected;
@Parameters
public static Collection dataGenerater() {
return Arrays.asList(new Object[][] {
{ "user01", "123456", true },
{ "helloworld", "123456", false },
{ "david", "re*ads", false },
{ "goodone", "onegood", true } });
}
public JunitSample(String user, String pw, boolean expected) {
this.user = user;
this.pw = pw;
this.expected = expected;
}
@Test
public void testAccessCheck() {
assertEquals(expected, UserAccess.accessCheck(user, pw));
}
}
運(yùn)行測(cè)試,顯示的測(cè)試結(jié)果如圖3所示。
圖3 測(cè)試結(jié)果
Fig.3 The test results
通過(guò)以上代碼可以看出,JUnit4通過(guò)使用一個(gè)標(biāo)記@Parameters注釋的返回類型為Collection的靜態(tài)方法產(chǎn)生數(shù)據(jù),測(cè)試數(shù)據(jù)通過(guò)變量傳遞給測(cè)試方法,從而完成多數(shù)據(jù)輸入的測(cè)試。但是隨著業(yè)務(wù)的需要,測(cè)試人員需要經(jīng)常增加測(cè)試數(shù)據(jù)與修改現(xiàn)有測(cè)試數(shù)據(jù),JUnit4提供的硬編碼方式已經(jīng)愈顯笨重和不便,數(shù)據(jù)與代碼分離顯得尤為重要。
本文所述的Feed4Junit可以良好 地解決數(shù)據(jù)與代碼分離的問(wèn)題,F(xiàn)eed4JUnit是JUnit測(cè)試框架的擴(kuò)展,它通過(guò)操作來(lái)自于文件以及不同的數(shù)據(jù)源的測(cè)試數(shù)據(jù),使單元測(cè)試變得更容易編寫與維護(hù)。本文通過(guò)實(shí)例展示Feed4JUnit的安裝以及測(cè)試代碼與數(shù)據(jù)分離的實(shí)現(xiàn),本文的實(shí)例代碼全部基于針對(duì)如下一個(gè)簡(jiǎn)單的用戶登錄檢驗(yàn)的類。
package sample.code;
public class UserAccess {
// simple validation for user name and password
public static boolean accessCheck(String userName, String password) {
if (userName.length() <= 4 || userName.length() > 8)
return false;
if (password.length() <= 4 || password.length() > 8)
return false;
if (userName.contains("@"))
return false;
if (password.contains("*"))
return false;
return true;
}
}
在靜態(tài)方法excel中,本文采用二維數(shù)組的方式來(lái)構(gòu)建測(cè)試所需要的參數(shù)列表,其中每個(gè)數(shù)組中的元素的放置順序并沒(méi)有什么要求,只要和構(gòu)造函數(shù)中的順序保持一致就可以了。現(xiàn)在如果再增加一種測(cè)試情況,只需要在靜態(tài)方法excel中添加相應(yīng)的數(shù)組即可,不再需要復(fù)制粘貼出一個(gè)新的方法出來(lái)了。
隨著項(xiàng)目的進(jìn)展,項(xiàng)目的規(guī)模在不斷地膨脹,為了保證項(xiàng)目的質(zhì)量,有計(jì)劃的執(zhí)行全面的單元測(cè)試是非常有必要的。但單靠JUnit提供的測(cè)試套件很難勝任這項(xiàng)工作,因?yàn)轫?xiàng)目中單元測(cè)試類的個(gè)數(shù)在不停的增加,測(cè)試套件卻無(wú)法動(dòng)態(tài)的識(shí)別新加入的單元測(cè)試類,需要手動(dòng)修改測(cè)試套件。
4 結(jié)論(Conclusion)
本文主要介紹了Junit相關(guān)單元測(cè)試技術(shù),分析了應(yīng)用Feed4JUnit進(jìn)行單元測(cè)試的方法,用戶可以方便的把測(cè)試數(shù)據(jù)存放在文件或其它數(shù)據(jù)源。通過(guò)提供簡(jiǎn)單的注釋,F(xiàn)eed4JUnit使用戶能夠極其方便的實(shí)施數(shù)據(jù)與代碼分離的測(cè)試,極大地增強(qiáng)了JUnit測(cè)試框架的易用性。本文所敘述的僅僅是Feed4JUnit提供的測(cè)試增強(qiáng)功能的一部分,Junit4同時(shí)還提供了大量數(shù)據(jù)的隨機(jī)測(cè)試和等價(jià)類測(cè)試等眾多功能。
參考文獻(xiàn)(References)
[1] 高共革,楊靜.基于.NET的單元測(cè)試自動(dòng)化方法研究[J].微計(jì)算機(jī)信息,2008,24(19):280-281.
[2] 吳高峽,王芙蓉.單元測(cè)試的自動(dòng)化實(shí)踐[J].計(jì)算機(jī)與數(shù)字工程,2007,35(1):174-176.
[3] 吳繼娟,孫媛媛,劉桂艷.基于BIST的FPGA邏輯單元測(cè)試方法[J].哈爾濱工業(yè)大學(xué)學(xué)報(bào),2004,36(8):1074-1076.
[4] 嚴(yán)俊,等.JUTA:一個(gè)Java自動(dòng)化單元測(cè)試工具[J].計(jì)算機(jī)研究與發(fā)展,2010(10):1840-1848.
[5] 張巍,尹海波,孫立財(cái).軟件的單元測(cè)試方法[J].光電技術(shù)應(yīng)用,2006,21(2):36-38.
作者簡(jiǎn)介:
楊 鵬(1978-),女,碩士,講師.研究領(lǐng)域:數(shù)據(jù)挖掘,圖形圖像處理,軟件測(cè)試.
endprint