楊鵬
摘要:軟件測試技術在軟件質(zhì)量控制過程中一直起著非常重要的作用。JUnit是被廣泛應用的Java單元測試框架,主要測試基于java語言編寫的程序代碼,用于編寫和運行可重復的測試。Feed4JUnit是開源的基于JUnit的擴展,通過使用Feed4JUnit提供的注釋,用戶可以很方便地把測試數(shù)據(jù)存放在文件或其他數(shù)據(jù)源。本文分析了應用Feed4JUnit進行單元測試的方法,并通過實際開發(fā)示例實現(xiàn)數(shù)據(jù)與代碼分離的測試。
關鍵詞:Feed4JUnit架構;單元測試;數(shù)據(jù)源
中圖分類號:TP311.52 文獻標識碼: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)
單元測試(Unit Testing),是指對軟件中的最小可測試單元進行檢查和驗證。對于單元測試中單元的含義,一般來說,要根據(jù)實際情況去判定其具體含義,如C語言中單元指一個函數(shù)[1],Java里單元指一個類,圖形化的軟件中可以指一個窗口或一個菜單等??偟膩碚f,單元就是人為規(guī)定的最小的被測功能模塊[2]。單元測試是在軟件開發(fā)過程中要進行的最低級別的測試活動,軟件的獨立單元將在與程序的其他部分相隔離的情況下進行測試[3]。單元測試不僅僅保證代碼在方法級別的正確性,它還能改進設計,易于對代碼重構[4]。凡是容易編寫單元測試的代碼,往往是優(yōu)秀的設計和松耦合的組件,凡是難于編寫單元測試的代碼,往往是設計不佳和耦合度高的系統(tǒng)[5]。因此,編寫單元測試不僅僅是掌握單元測試柜架的用法,更重要的是在編寫單元測試的過程中發(fā)現(xiàn)設計缺陷,改進系統(tǒng)結構,從而實現(xiàn)良好的可擴展性。
任何一個項目,單元測試應該在詳細設計之后開始進行,首先根據(jù)詳細設計文檔進行單元測試用例的編寫,編寫完成后進行代碼開發(fā),代碼完成后運行單元測試,如果通過,則該方法可以發(fā)布運行,如果不通過需要進行代碼改造,再進行單元測試,直到單元測試運行通過為止。
2 Junit單元測試架構(Junit unit test framework)
JUnit是由Erich Gamma和Kent Beck編寫的一個回歸測試框架(Regression Testing Framework)。Junit測試是程序員測試,即所謂白盒測試,因為程序員知道被測試的軟件如何(How)完成功能和完成什么樣(What)的功能。Junit是一套框架,繼承TestCase類,就可以用Junit進行自動測試了。通常來說,在極限編程中,基本過程是這樣的:構思→編寫測試代碼→編寫代碼→測試,而且編寫測試和編寫代碼都是增量式的,寫一點測一點,在編寫以后的代碼中如果發(fā)現(xiàn)問題可以較快的追蹤到問題的原因,減小回歸錯誤的糾錯難度,如圖1所示的是Junit基本架構。
圖1 Junit基本架構
Fig.1 The basic architecture of Junit
在Junit類中,有很多定義類。Test:是TestCase、TestSuite的共同接口。run(TestResult)用來運行Test,并且將結果保存到TestResult。TestCase:Test的接口的抽象實現(xiàn),是Abstract類,所以不能實例化,能被繼承。其中一個構造函數(shù)TestCase(String Name),根據(jù)輸入的參數(shù),創(chuàng)建一個測試實例。參數(shù)為該類的以test開頭的方法名,把它添加到TestSuite中,指定僅僅運行TestCase中的一個方法。
TestSuite:實現(xiàn)Test接口??梢越M裝一個或者多個TestCase。待測試類中可能包括了對被測類的多個TestCase,而TestSuit可以保存多個TestCase,負責收集這些測試,這樣就可以一個Suite就能運行對被測類的多個測試。TestResult:保存TestCase運行中的事件。TestResult有List
ResultPrinter:實現(xiàn)TestListener接口。在TestCase運行過程中,對所監(jiān)聽的對象的事件以一定格式及時輸出,運行完后,對TestResult對象進行分析,輸出的統(tǒng)計結果。BaseTestRunner:所有TestRunner的超類。java Junit.swingui.TestRunner:實BaseTestRunner,提供圖形界面。java Junit.textui.TestRunner:實現(xiàn)BaseTestRunner,提供文本界面。下面將以它做為例子講解JUnit生命周期。
3 JUnit4測試實例(JUnit4 test examples)
在應用程序的業(yè)務邏輯中存在大量的這樣的接口:他們接受不同的輸入,然后進行或驗證、或處理,進而完成相同的流程。比如網(wǎng)站的登錄入口,用戶名和密碼都有長度的限制,同時也具有是否允許特殊字符的限制等,所以在我們進行其單元測試的過程中,根據(jù)不同長度的用戶名和密碼,以及不同的字符組合,只需要提供相同的測試代碼結構,就能完成測試,不同的僅僅測試數(shù)據(jù)與期望值,但是因為每一個測試方法中的輸入?yún)?shù)不同,我們必須為每一個輸入組編寫單獨的測試用例,從而產(chǎn)生大量冗余代碼,十分不便于維護。
將Java對象名稱(每個單詞的頭字母大寫)按照數(shù)據(jù)庫命名的習慣進行格式化,格式化后的數(shù)據(jù)為小寫字母,并且使用下劃線分割命名單詞,要求對輸入數(shù)據(jù)進行非法驗證。
首先新建一個TestJUnit。打開項目TestJUnit的屬性頁→選擇“Java Build Path”子選項→點選“Add Library…”按鈕→在彈出的“Add Library”對話框中選擇JUnit(圖2),并在下一頁中選擇版本4.1后點擊“Finish”按鈕。
圖2 JUnit 運行測試界面
Fig.2 JUnit run the test interface
在JUnit運行界面提示有兩個測試情況未通過,當首字母大寫時得到的處理結果與預期的有偏差,造成測試失??;而當測試對 null的處理結果時,則直接拋出了異常,測試錯誤。
JUnit將測試失敗的情況分為兩種:failure和error。Failure一般由單元測試使用的斷言方法判斷失敗引起,它表示在測試點發(fā)現(xiàn)了問題;而error則是由代碼異常引起,這是測試目的之外的發(fā)現(xiàn),它可能產(chǎn)生于測試代碼本身的錯誤(測試代碼也是代碼,同樣無法保證完全沒有缺陷),也可能是被測試代碼中的一個隱藏的bug。顯然,被測試代碼中并沒有對首字母大寫和null這兩種特殊情況進行處理,現(xiàn)在對源代碼進行修改,添加對這兩種情況的處理,代碼如下:
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));
}
}
運行測試,顯示的測試結果如圖3所示。
圖3 測試結果
Fig.3 The test results
通過以上代碼可以看出,JUnit4通過使用一個標記@Parameters注釋的返回類型為Collection的靜態(tài)方法產(chǎn)生數(shù)據(jù),測試數(shù)據(jù)通過變量傳遞給測試方法,從而完成多數(shù)據(jù)輸入的測試。但是隨著業(yè)務的需要,測試人員需要經(jīng)常增加測試數(shù)據(jù)與修改現(xiàn)有測試數(shù)據(jù),JUnit4提供的硬編碼方式已經(jīng)愈顯笨重和不便,數(shù)據(jù)與代碼分離顯得尤為重要。
本文所述的Feed4Junit可以良好 地解決數(shù)據(jù)與代碼分離的問題,F(xiàn)eed4JUnit是JUnit測試框架的擴展,它通過操作來自于文件以及不同的數(shù)據(jù)源的測試數(shù)據(jù),使單元測試變得更容易編寫與維護。本文通過實例展示Feed4JUnit的安裝以及測試代碼與數(shù)據(jù)分離的實現(xià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ù)組的方式來構建測試所需要的參數(shù)列表,其中每個數(shù)組中的元素的放置順序并沒有什么要求,只要和構造函數(shù)中的順序保持一致就可以了?,F(xiàn)在如果再增加一種測試情況,只需要在靜態(tài)方法excel中添加相應的數(shù)組即可,不再需要復制粘貼出一個新的方法出來了。
隨著項目的進展,項目的規(guī)模在不斷地膨脹,為了保證項目的質(zhì)量,有計劃的執(zhí)行全面的單元測試是非常有必要的。但單靠JUnit提供的測試套件很難勝任這項工作,因為項目中單元測試類的個數(shù)在不停的增加,測試套件卻無法動態(tài)的識別新加入的單元測試類,需要手動修改測試套件。
4 結論(Conclusion)
本文主要介紹了Junit相關單元測試技術,分析了應用Feed4JUnit進行單元測試的方法,用戶可以方便的把測試數(shù)據(jù)存放在文件或其它數(shù)據(jù)源。通過提供簡單的注釋,F(xiàn)eed4JUnit使用戶能夠極其方便的實施數(shù)據(jù)與代碼分離的測試,極大地增強了JUnit測試框架的易用性。本文所敘述的僅僅是Feed4JUnit提供的測試增強功能的一部分,Junit4同時還提供了大量數(shù)據(jù)的隨機測試和等價類測試等眾多功能。
參考文獻(References)
[1] 高共革,楊靜.基于.NET的單元測試自動化方法研究[J].微計算機信息,2008,24(19):280-281.
[2] 吳高峽,王芙蓉.單元測試的自動化實踐[J].計算機與數(shù)字工程,2007,35(1):174-176.
[3] 吳繼娟,孫媛媛,劉桂艷.基于BIST的FPGA邏輯單元測試方法[J].哈爾濱工業(yè)大學學報,2004,36(8):1074-1076.
[4] 嚴俊,等.JUTA:一個Java自動化單元測試工具[J].計算機研究與發(fā)展,2010(10):1840-1848.
[5] 張巍,尹海波,孫立財.軟件的單元測試方法[J].光電技術應用,2006,21(2):36-38.
作者簡介:
楊 鵬(1978-),女,碩士,講師.研究領域:數(shù)據(jù)挖掘,圖形圖像處理,軟件測試.
endprint
將Java對象名稱(每個單詞的頭字母大寫)按照數(shù)據(jù)庫命名的習慣進行格式化,格式化后的數(shù)據(jù)為小寫字母,并且使用下劃線分割命名單詞,要求對輸入數(shù)據(jù)進行非法驗證。
首先新建一個TestJUnit。打開項目TestJUnit的屬性頁→選擇“Java Build Path”子選項→點選“Add Library…”按鈕→在彈出的“Add Library”對話框中選擇JUnit(圖2),并在下一頁中選擇版本4.1后點擊“Finish”按鈕。
圖2 JUnit 運行測試界面
Fig.2 JUnit run the test interface
在JUnit運行界面提示有兩個測試情況未通過,當首字母大寫時得到的處理結果與預期的有偏差,造成測試失??;而當測試對 null的處理結果時,則直接拋出了異常,測試錯誤。
JUnit將測試失敗的情況分為兩種:failure和error。Failure一般由單元測試使用的斷言方法判斷失敗引起,它表示在測試點發(fā)現(xiàn)了問題;而error則是由代碼異常引起,這是測試目的之外的發(fā)現(xiàn),它可能產(chǎn)生于測試代碼本身的錯誤(測試代碼也是代碼,同樣無法保證完全沒有缺陷),也可能是被測試代碼中的一個隱藏的bug。顯然,被測試代碼中并沒有對首字母大寫和null這兩種特殊情況進行處理,現(xiàn)在對源代碼進行修改,添加對這兩種情況的處理,代碼如下:
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));
}
}
運行測試,顯示的測試結果如圖3所示。
圖3 測試結果
Fig.3 The test results
通過以上代碼可以看出,JUnit4通過使用一個標記@Parameters注釋的返回類型為Collection的靜態(tài)方法產(chǎn)生數(shù)據(jù),測試數(shù)據(jù)通過變量傳遞給測試方法,從而完成多數(shù)據(jù)輸入的測試。但是隨著業(yè)務的需要,測試人員需要經(jīng)常增加測試數(shù)據(jù)與修改現(xiàn)有測試數(shù)據(jù),JUnit4提供的硬編碼方式已經(jīng)愈顯笨重和不便,數(shù)據(jù)與代碼分離顯得尤為重要。
本文所述的Feed4Junit可以良好 地解決數(shù)據(jù)與代碼分離的問題,F(xiàn)eed4JUnit是JUnit測試框架的擴展,它通過操作來自于文件以及不同的數(shù)據(jù)源的測試數(shù)據(jù),使單元測試變得更容易編寫與維護。本文通過實例展示Feed4JUnit的安裝以及測試代碼與數(shù)據(jù)分離的實現(xià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ù)組的方式來構建測試所需要的參數(shù)列表,其中每個數(shù)組中的元素的放置順序并沒有什么要求,只要和構造函數(shù)中的順序保持一致就可以了。現(xiàn)在如果再增加一種測試情況,只需要在靜態(tài)方法excel中添加相應的數(shù)組即可,不再需要復制粘貼出一個新的方法出來了。
隨著項目的進展,項目的規(guī)模在不斷地膨脹,為了保證項目的質(zhì)量,有計劃的執(zhí)行全面的單元測試是非常有必要的。但單靠JUnit提供的測試套件很難勝任這項工作,因為項目中單元測試類的個數(shù)在不停的增加,測試套件卻無法動態(tài)的識別新加入的單元測試類,需要手動修改測試套件。
4 結論(Conclusion)
本文主要介紹了Junit相關單元測試技術,分析了應用Feed4JUnit進行單元測試的方法,用戶可以方便的把測試數(shù)據(jù)存放在文件或其它數(shù)據(jù)源。通過提供簡單的注釋,F(xiàn)eed4JUnit使用戶能夠極其方便的實施數(shù)據(jù)與代碼分離的測試,極大地增強了JUnit測試框架的易用性。本文所敘述的僅僅是Feed4JUnit提供的測試增強功能的一部分,Junit4同時還提供了大量數(shù)據(jù)的隨機測試和等價類測試等眾多功能。
參考文獻(References)
[1] 高共革,楊靜.基于.NET的單元測試自動化方法研究[J].微計算機信息,2008,24(19):280-281.
[2] 吳高峽,王芙蓉.單元測試的自動化實踐[J].計算機與數(shù)字工程,2007,35(1):174-176.
[3] 吳繼娟,孫媛媛,劉桂艷.基于BIST的FPGA邏輯單元測試方法[J].哈爾濱工業(yè)大學學報,2004,36(8):1074-1076.
[4] 嚴俊,等.JUTA:一個Java自動化單元測試工具[J].計算機研究與發(fā)展,2010(10):1840-1848.
[5] 張巍,尹海波,孫立財.軟件的單元測試方法[J].光電技術應用,2006,21(2):36-38.
作者簡介:
楊 鵬(1978-),女,碩士,講師.研究領域:數(shù)據(jù)挖掘,圖形圖像處理,軟件測試.
endprint
將Java對象名稱(每個單詞的頭字母大寫)按照數(shù)據(jù)庫命名的習慣進行格式化,格式化后的數(shù)據(jù)為小寫字母,并且使用下劃線分割命名單詞,要求對輸入數(shù)據(jù)進行非法驗證。
首先新建一個TestJUnit。打開項目TestJUnit的屬性頁→選擇“Java Build Path”子選項→點選“Add Library…”按鈕→在彈出的“Add Library”對話框中選擇JUnit(圖2),并在下一頁中選擇版本4.1后點擊“Finish”按鈕。
圖2 JUnit 運行測試界面
Fig.2 JUnit run the test interface
在JUnit運行界面提示有兩個測試情況未通過,當首字母大寫時得到的處理結果與預期的有偏差,造成測試失?。欢敎y試對 null的處理結果時,則直接拋出了異常,測試錯誤。
JUnit將測試失敗的情況分為兩種:failure和error。Failure一般由單元測試使用的斷言方法判斷失敗引起,它表示在測試點發(fā)現(xiàn)了問題;而error則是由代碼異常引起,這是測試目的之外的發(fā)現(xiàn),它可能產(chǎn)生于測試代碼本身的錯誤(測試代碼也是代碼,同樣無法保證完全沒有缺陷),也可能是被測試代碼中的一個隱藏的bug。顯然,被測試代碼中并沒有對首字母大寫和null這兩種特殊情況進行處理,現(xiàn)在對源代碼進行修改,添加對這兩種情況的處理,代碼如下:
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));
}
}
運行測試,顯示的測試結果如圖3所示。
圖3 測試結果
Fig.3 The test results
通過以上代碼可以看出,JUnit4通過使用一個標記@Parameters注釋的返回類型為Collection的靜態(tài)方法產(chǎn)生數(shù)據(jù),測試數(shù)據(jù)通過變量傳遞給測試方法,從而完成多數(shù)據(jù)輸入的測試。但是隨著業(yè)務的需要,測試人員需要經(jīng)常增加測試數(shù)據(jù)與修改現(xiàn)有測試數(shù)據(jù),JUnit4提供的硬編碼方式已經(jīng)愈顯笨重和不便,數(shù)據(jù)與代碼分離顯得尤為重要。
本文所述的Feed4Junit可以良好 地解決數(shù)據(jù)與代碼分離的問題,F(xiàn)eed4JUnit是JUnit測試框架的擴展,它通過操作來自于文件以及不同的數(shù)據(jù)源的測試數(shù)據(jù),使單元測試變得更容易編寫與維護。本文通過實例展示Feed4JUnit的安裝以及測試代碼與數(shù)據(jù)分離的實現(xià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ù)組的方式來構建測試所需要的參數(shù)列表,其中每個數(shù)組中的元素的放置順序并沒有什么要求,只要和構造函數(shù)中的順序保持一致就可以了?,F(xiàn)在如果再增加一種測試情況,只需要在靜態(tài)方法excel中添加相應的數(shù)組即可,不再需要復制粘貼出一個新的方法出來了。
隨著項目的進展,項目的規(guī)模在不斷地膨脹,為了保證項目的質(zhì)量,有計劃的執(zhí)行全面的單元測試是非常有必要的。但單靠JUnit提供的測試套件很難勝任這項工作,因為項目中單元測試類的個數(shù)在不停的增加,測試套件卻無法動態(tài)的識別新加入的單元測試類,需要手動修改測試套件。
4 結論(Conclusion)
本文主要介紹了Junit相關單元測試技術,分析了應用Feed4JUnit進行單元測試的方法,用戶可以方便的把測試數(shù)據(jù)存放在文件或其它數(shù)據(jù)源。通過提供簡單的注釋,F(xiàn)eed4JUnit使用戶能夠極其方便的實施數(shù)據(jù)與代碼分離的測試,極大地增強了JUnit測試框架的易用性。本文所敘述的僅僅是Feed4JUnit提供的測試增強功能的一部分,Junit4同時還提供了大量數(shù)據(jù)的隨機測試和等價類測試等眾多功能。
參考文獻(References)
[1] 高共革,楊靜.基于.NET的單元測試自動化方法研究[J].微計算機信息,2008,24(19):280-281.
[2] 吳高峽,王芙蓉.單元測試的自動化實踐[J].計算機與數(shù)字工程,2007,35(1):174-176.
[3] 吳繼娟,孫媛媛,劉桂艷.基于BIST的FPGA邏輯單元測試方法[J].哈爾濱工業(yè)大學學報,2004,36(8):1074-1076.
[4] 嚴俊,等.JUTA:一個Java自動化單元測試工具[J].計算機研究與發(fā)展,2010(10):1840-1848.
[5] 張巍,尹海波,孫立財.軟件的單元測試方法[J].光電技術應用,2006,21(2):36-38.
作者簡介:
楊 鵬(1978-),女,碩士,講師.研究領域:數(shù)據(jù)挖掘,圖形圖像處理,軟件測試.
endprint