轉載-使用 Feed4JUnit 進行數據與代碼分離的 Java 單元測試

?

JUnit 是被廣泛應用的 Java 單元測試框架,但是它沒有很好的提供參數化測試的支持,很多測試人員不得不把測試數據寫在程序里或者通過其它方法實現數據與代碼的分離,在后續的修改和維護上有諸多限制和不便。Feed4JUnit 是開源的基于 JUnit 的擴展,通過使用 Feed4JUnit 提供的注釋,用戶可以很方便的把測試數據存放在文件或其它數據源。本文通過介紹及簡單示例,使讀者了解并能夠使用 Feed4JUnit, 方便的實現數據與代碼分離的測試。

Feed4JUnit 與 JUnit

經常,在應用程序的業務邏輯中存在大量的這樣的接口:他們接受不同的輸入,然后進行或驗證,或處理,進而完成相同的流程。比如網站的登錄入口,用戶名和密碼都有長度的限制,同時也具有是否允許特殊字符的限制等,所以在我們進行其單元測試的過程中,根據不同長度的用戶名和密碼,以及不同的字符組合,只需要提供相同的測試代碼結構,就能完成測試,不同的僅僅測試數據與期望值,但是因為每一個測試方法中的輸入參數不同,我們必須為每一個輸入組編寫單獨的測試用例,從而產生大量冗余代碼,十分不便于維護。

基于以上場景,JUnit 4 提供了參數化的特性,從而能夠實現不同數據輸入對相同測試代碼的測試,如清單 1 所示:

清單 1. JUnit 4 參數化測試代碼示例
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;@Parameterspublic 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;}@Testpublic void testAccessCheck() {assertEquals(expected, UserAccess.accessCheck(user, pw));}
}

通過以上示例代碼可以看出,JUnit 4 通過使用一個標記 @Parameters 注釋的返回類型為 Collection 的靜態方法產生數據,測試數據通過變量傳遞給測試方法,從而完成多數據輸入的測試。但是隨著業務的需要,測試人員需要經常增加測試數據與修改現有測試數據,JUnit 4 提供的硬編碼方式已經愈顯笨重和不便,數據與代碼分離顯得尤為重要。

幸好,本文所述的 Feed4JUnit 良好的解決了數據與代碼分離的問題,Feed4JUnit 是 JUnit 測試框架的擴展,它通過操作來自于文件以及不同的數據源的測試數據,使您的單元測試變得更容易編寫與維護。

本文將通過示例向您展示 Feed4JUnit 的安裝以及測試代碼與數據分離的實現,請注意本文的示例代碼全部基于針對如下一個十分簡單用戶登錄檢驗的類,并且假定您正在使用 Eclipse 作為您的 IDE,請看清單 2 類代碼:

清單 2. 實例類
package sample.code;public class UserAccess {// simple validation for user name and passwordpublic 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;}
}

Feed4JUnit 的下載及安裝

1. Feed4JUnit 是開源的測試組件,您可以從如下鏈接下載最新版本:

http://sourceforge.net/projects/feed4junit/files/

2. 解壓下載的 zip 包,復制整個 lib 文件夾到您的 Java 項目的根目錄,如圖 1:

圖 1. 復制 lib 到項目根目錄
圖 1. 復制 lib 到項目根目錄

3. 選定項目,右鍵選擇項目的屬性,然后通過 Add JARs 將步驟 2 中 lib 文件夾下的所有 Jar 添加到項目的 Build Path 下,如圖 2

圖 2. 添加 Jar 到 Build Path
圖 2. 添加 Jar 到 Build Path

通過以上三步,您已經準備好您的 Feed4JUnit 環境并可以開始使用它,當然,開發測試代碼之前,您必需要將 Feed4JUnit 相應的包 Import 進您的類。

使用 Feed4JUnit 實現數據與代碼分離的測試

Feed4JUnit 的數據源可以包括以下幾種類型 - 文件 (CSV 或者 Excel?)、數據庫、自定義數據源。

Feed4JUnit 使用一個特殊的運行類 Feeder.class,用來支持與標識參數化測試,如果您想要編寫數據與代碼分離的測試腳本,必須在您的測試類上增加注釋 @RunWith(Feeder.class) 。同時,您需要使用 @Test 來標示您實現測試的方法,并且使用 @Source 來聲明和接收數據源的數據,基本的代碼結構如清單 3 所示:

清單 3. 基本代碼結構
package sample.test;import static org.junit.Assert.assertEquals;
import org.databene.feed4junit.Feeder;
import org.databene.benerator.anno.Source;
import org.junit.Test;
import org.junit.runner.RunWith;/** Feed4JUnit - @RunWith, @Test and @Source*/
@RunWith(Feeder.class) //Specify the class will be ran as Feeder class
public class Feed4JSample {@Test //Specify the method as a test method@Source()//Specify the input data sourcepublic void testAccessCheck() {assertEquals(true, true);}
}

以文件作為數據源

Feed4JUnit 支持從 CSV 或者 Excel 文件里面讀取數據作為輸入,這里我們以 Excel 文件為例。

1. 在測試項目的根目錄下創建 Data.xls 數據文件,樣例數據如圖 3,默認情況下,第一行會以列名存在,在運行過程中不會作為數據讀取。

圖 3. Excel 數據源
圖 3. Excel 數據源

2. 創建測試類并在接收數據的測試方法上聲明數據源為 @Source("Data.xls"),Excel 中的數據在傳遞過程中會自動按照列與測試方法的參數的位置順序進行匹配,并以行作為一個單位讀取并傳遞給測試方法體。比如圖 3 中的 user 列的值會做為方法的第一個參數傳入方法體中,pw 列的值會作為方法的第二個參數,以此類推。在測試進行過程中,首先在 Excel 文件中讀取一行(包含三列),接著按照位置順序將數據傳遞到方法體中(每列按順序對應一個參數)進行執行,執行完成后讀取 Excel 中的下一行進行相同流程的測試,其原理與 Java 中的迭代器十分類似。請注意當數據文件中數據的列數小于測試方法參數的個數的時候,測試會因為位置不匹配而失敗。

清單 4 包括從 CSV 和 Excel 讀取和傳遞數據的示例:

清單 4. 文件數據源示例
package sample.test;import static org.junit.Assert.assertEquals;import org.databene.benerator.anno.Source;
import org.databene.feed4junit.Feeder;
import org.junit.Test;
import org.junit.runner.RunWith;import sample.code.UserAccess;/** Feed4JUnit - Get Data from CSV/Excel File source*/@RunWith(Feeder.class)
public class F4JfromFile {@Test@Source("Data.csv")//CSV sourcepublic void testAccessCheck_CSV(String userName, String pw, boolean expected) {assertEquals(expected, UserAccess.accessCheck(userName, pw));}@Test@Source("Data.xls")//Excel sourcepublic void testAccessCheck_Excel(String userName, String pw, boolean expected) {assertEquals(expected, UserAccess.accessCheck(userName, pw));}
}

3. 運行測試,因為 Feed4Junit 是 JUnit 的擴展,所以運行方式與 JUnit 完全相同,即以 JUnit 運行即可,運行結果如圖 4 所示,我們可以看到,Data.xls 中的數據已全部傳入測試方法并運行。

圖 4. 運行結果示例
圖 4. 運行結果示例

以數據庫作為數據源

通過使用 @Database ,您可以很方便的使用來自于數據庫的數據,這在進行大量測試數據測試的時候或者復用現有的應用業務數據作為測試數據的情況下比較有用。

當您使用來自數據庫的數據源的時候,首先必須使用 @Database 聲明數據庫的信息 ,可以為類或方法添加 @Database 注釋 , 如果注釋類為 @Database 的時候,類中所有的方法都可以使用此數據庫的數據作為源,當聲明 @Database 于方法的時候,此類中僅此方法可以調用數據庫作為數據源。@ Database 具有一些屬性,用于聲明用于連接數據庫信息,請看一下說明:

id: 一個用于標識數據庫數據源標識符,在測試方法的 @Source 中進行引用關聯

url:數據庫的 URL

driver: 數據庫的驅動

user: 數據庫的用戶名

password:數據庫的密碼

完成以上數據庫的定義后,需要在測試方法的 @Source 中引用您所需要的庫,使用屬性 id 和 selector 可以完成此操作:

id: @Source 中的 id 和 @Database 的 id 相對應關聯

selector:SQL 語句,用于查詢出相應的數據傳遞給測試方法

以下我們以 DB2 作為數據源,使用 DB2 的 Sample 數據庫,并創建名為 TEST 的表來存儲測試數據,測試數據與圖 3 Excel 數據源的完全相同,請看圖 5。

圖 5. 數據表中的測試數據
圖 5. 數據表中的測試數據

首先,創建測試類,添加 @Database 注釋并增加數據庫的連接信息,同時指定一個表示數據庫的 id,在測試方法的 @Source 中通過 id 進行關聯,并制定 selector 的語句進行數據查詢,例如本例中的 selector = "select * from TEST",會從 TEST 表中取出全部數據用于測試,細節請參考以下代碼示例:

清單 5 為在類上聲明 @Database。

清單 5. 在類上聲明 @Database
package sample.test;import static org.junit.Assert.assertEquals;import org.databene.benerator.anno.Database;
import org.databene.benerator.anno.Source;
import org.databene.feed4junit.Feeder;
import org.junit.Test;
import org.junit.runner.RunWith;import sample.code.UserAccess;/** Feed4JUnit - Get Data from Database, all test methods can use the database data*/
@RunWith(Feeder.class)
@Database(id = "testdb", url = "jdbc:db2://localhost:50000/SAMPLE", driver = "com.ibm.db2.jcc.DB2Driver", user = "db2admin", password = "db2admin")
public class F4JfromDB {@Test@Source(id = "testdb", selector = "select * from TEST")public void testAccessCheck(String userName, String pw, String expected) {Boolean bSucess = UserAccess.accessCheck(userName.trim(), pw.trim());assertEquals(expected.trim(), bSucess.toString());}
}

清單 6 為在方法上聲明 @Database:

清單 6. 在方法上聲明 @Database
/** Feed4JUnit - Get Data from Database, only the specified method can use the database data*/@RunWith(Feeder.class)
public class F4JfromDB_Method {@Test@Database(id = "testdb", url = "jdbc:db2://localhost:50000/SAMPLE", driver = "com.ibm.db2.jcc.DB2Driver", user = "db2admin", password = "db2admin")@Source(id = "testdb", selector = "select * from TEST")public void testAccessCheck(String userName, String pw, String expected) {Boolean bSucess = UserAccess.accessCheck(userName.trim(), pw.trim());assertEquals(expected.trim(), bSucess.toString());}
}

測試運行過程中,通過 url,driver 等信息建立數據連接,通過 selector 發出數據請求,最后完成查詢并把數據傳遞給測試方法,數據在傳遞給方法的時候,會按數據表的列的順序與參數進行匹配,運行結果與圖 4 類似。

自定義數據源

除了 CSV,Excel 和數據庫的數據源外,Feed4JUnit 還提供自定義數據源,以滿足不同用戶的需求,用戶同樣可以通過封裝 JUnit 4 提供的參數化測試的方法來完成數據源自定義,所有這里作者不再詳述,用戶可以封裝并取得不同的數據源的數據,傳遞給 Feed4JUnit 的相應接口,來完成數據源的自定義。

結束語

本文通過對比介紹和簡單易懂的實例全面講解了 Feed4JUnit 對數據與代碼分離的測試支持。通過提供簡單的注釋,Feed4JUnit 使用戶能夠極其方便的實施數據與代碼分離的測試,極大地增強了 JUnit 測試框架的易用性。 相信您已經在本文的敘述中看到它的優點。同時,本文所敘述的僅僅是 Feed4JUnit 提供的測試增強功能的一部分,Feed4JUnit 同時還提供了大量數據的隨機測試和等價類測試等眾多功能,如果您感興趣可以自行參考。

轉載于:https://www.cnblogs.com/testermark/p/4075365.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/258021.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/258021.shtml
英文地址,請注明出處:http://en.pswp.cn/news/258021.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

青島智能院助力智慧城市 打造智能產業“黃埔軍校”

作為青島市的主干道之一&#xff0c;山東路的擁堵狀況一直讓人頭疼。近日&#xff0c;因為一種交通組織優化方案的實施&#xff0c;山東路和延吉路的通行率提高了近50%。而研發這種智能管控系統的正是位于青島高新區的青島智能產業技術研究院。截止今年5月份&#xff0c;青島智…

oracle備份歸檔文件,oracle 如何不備份已經備份的歸檔

在Oracle數據庫備份歸檔日志時&#xff0c;通常會保存最近幾天的歸檔日志文件不刪除。如&#xff1a;backup archivelog all;delete noprompt archivelog all completed before sysdate -14; 在本地保留14天的歸檔日志&#xff0e;再備份時&#xff0c;歸檔會重復再備份一次。…

博客遷移指南

1.今天起 博客遷移至farbox 2. 新博客地址&#xff0c;http://yoon.farbox.com轉載于:https://www.cnblogs.com/yoon/p/5003384.html

iOS 第三方登錄 !

http://www.it165.net/pro/html/201409/21854.html 轉載于:https://www.cnblogs.com/Seeulater/p/4076727.html

dp遞推 hdu1978

How many ways Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5422 Accepted Submission(s): 3185 Problem Description這是一個簡單的生存游戲&#xff0c;你控制一個機器人從一個棋盤的起始點(1,1)走到棋盤的…

codeforce-600C. Make Palindrome(貪心)

http://codeforces.com/problemset/problem/600/C&#xff1b; 題意&#xff1a;給你一個小寫字母組成的英文串&#xff0c;將它轉換為回文串&#xff0c;要求&#xff0c;改變的字母的個數最小&#xff0c;移動字母不算改變字母。 所得的串字典序是最小的。最后輸出所得到的串…

oracle觸發器沒有效果,觸發器不起作用,各位幫忙看看什么原因?

測試數據模型如下&#xff1a;Create Table test_c (Id Number,seq Number,state varchar2(5));select a.*,rowid from test_c aInsert Into test_cValues(1011,101,00A);Insert Into test_cValues(1012,101,00A);Insert Into test_cValues(1021,102,00A);Insert Into test_cVa…

10個我最喜歡問程序員的面試問題

最近我拜讀很多文章&#xff0c;都是介紹面試問題的&#xff0c;我真心不理解&#xff0c;面試官代表公司想要聘用的是最優秀的程序員&#xff0c;那就意味著需要想出一些有意義的面試問題。如果你就提一些毫無用處的垃圾問題&#xff0c;那么很容易遺漏很多能干的程序員。當然…

oracle動態性能視圖和靜態,oracle最重要的9個動態性能視圖

v$session v$session_wait (在10g里功能被整合,湊合算1個吧.)v$processv$sqlv$sqltextv$bh (更寧愿是x$bh)v$lockv$latch_childrenv$sysstatv$system_event按組分的幾組重要的性能視圖1。System 的 over viewv$sysstat , v$system_event , v$parameter2。某個session 的當前情況…

glTF格式初步了解

glTF格式初步了解近期看到Qt 3D的進展。偶然了解到了一種新的格式&#xff1a;glTF格式。這樣的格式據說比現有的3D格式更加符合OpenGL應用的須要。這引起了我的好奇。于是我在Qt 3D的外部鏈接中找到了有關glTF的相關鏈接。上海萌夢信息科技有限公司&#xff08;微博&#xff1…

【】局部刷新:

【】局部刷新&#xff1a; //頁面加載時綁定按鈕點擊事件$(function(){ $("#按鈕id").click(function(){ refresh(); });});//點擊按鈕調用的方法function refresh(){ window.location.reload();//刷新當前頁面. //或者下方刷新方法 //par…

技術貼-搜狗打字

超強技術帖&#xff1a;遇到不會讀的字&#xff0c;怎么用拼音打出來&#xff1f;】方法很簡單&#xff0c;就是先打個“u”然后打各個部首的讀音&#xff0c;就能在拼音輸入法中打出來哦。比如&#xff0c;骉&#xff0c;可以輸入umamama&#xff0c;輸入法就會自動出現“骉”…

【第二十七章】 springboot + zipkin(brave-okhttp實現)

本文截取自&#xff1a;http://blog.csdn.net/liaokailin/article/details/52077620 一、前提 1、zipkin基本知識&#xff1a;附8 zipkin 2、啟動zipkin server&#xff1a; 2.1、在官網下載服務jar&#xff0c;http://zipkin.io/pages/quickstart.html&#xff0c;之后使用命令…

Oracle 數據定義語言,oracle 數據定義語言(DDL)語法

DDL語言包括數據庫對象的創建(create)、刪除(drop)和修改(alter)的操作1.創建表語法create table table_name(column_name datatype [null | not null],column_name datatype [null | not null],..........[constraint])constraint 是為表中的列設置約束&#xff0c;常見的有…

Android內存泄漏問題(一)

前言 不少人認為JAVA程序&#xff0c;因為有垃圾回收機制&#xff0c;應該沒有內存泄露。 其實如果我們一個程序中&#xff0c;已經不再使用某個對象&#xff0c;但是因為仍然有引用指向它&#xff0c;垃圾回收器就無法回收它&#xff0c;當然該對象占用的內存就無法被使用&…

向上彈出菜單jQuery插件

插件名&#xff1a;柯樂義英文名&#xff1a;Keleyijs文件名稱&#xff1a;jquery.keleyi.js插件功能&#xff1a;該插件可以讓你輕易地在頁面上構建一個向上彈出的二級菜單。支持瀏覽器&#xff1a;keleyi 0.1.4版本支持IE6以及以上、Chrome、火狐(Firefox)、歐朋(Opera)、Saf…

oracle在線sql數據庫設計,一款在線ER模型設計工具,支持MySQL、SQLServer、Oracle、Postgresql...

在線QQ客服&#xff1a;1922638專業的SQL Server、MySQL數據庫同步軟件介紹一個在線ER模型生成工具&#xff0c;該工具可以在線為多個數據庫的DDL文件生成ER模型圖&#xff0c;并支持MySQL&#xff0c;SQLServer&#xff0c;Oracle&#xff0c;PostgreSQL和其他數據庫。主要功能…

_M_invoke(_Index_tuple_Indices...)

2019獨角獸企業重金招聘Python工程師標準>>> [hadoopiZ25s7cmfyrZ C_script]$ cat test_thread_a.cpp #include <iostream> #include <atomic> #include <thread> #include <vector>std::atomic<int> global_counter(0);void increa…

十年后2023年再讀這篇文章,看看我將會怎么樣?

http://blog.csdn.net/wojiushiwo987/article/details/8453881看到一篇文章不錯【清華差生10年奮斗經歷】 &#xff0c;寫給將要工作的自己&#xff0c;十年后2023年再讀這篇文章&#xff0c;看看我將會怎么樣&#xff1f; 在2012年收關時刻&#xff0c;看到如此激勵的文章&…

1203正規式轉換為有窮自動機

1 #include<stdio.h>2 #include <ctype.h>3 #define ok 14 #define error 05 #define MAXREGLUARLONG 406 #define MAXSTATELONG 40 7 #define MAXCAHRSLONG 40 8 typedef int state;9 int iCurrentState0; //初態以1開始10 int iPreState0;11 in…