汪添生,馬朝晗,崔 蔚,劉 迪,4,趙俊峰,夏 飛
1(國網(wǎng)信息通信產(chǎn)業(yè)集團有限公司,北京 100761)
2(廈門億力吉奧信息科技有限公司,廈門 361000)
3(國網(wǎng)信通產(chǎn)業(yè)集團億力科技公司,北京 100053)
4(北京中電普華信息技術(shù)有限公司,北京 100085)
5(國網(wǎng)江蘇省電力公司通信分公司,南京 210008)
基于多線程并發(fā)的JUnit與TestNG測試框架比較①
汪添生1,2,馬朝晗3,崔 蔚1,劉 迪1,4,趙俊峰5,夏 飛5
1(國網(wǎng)信息通信產(chǎn)業(yè)集團有限公司,北京 100761)
2(廈門億力吉奧信息科技有限公司,廈門 361000)
3(國網(wǎng)信通產(chǎn)業(yè)集團億力科技公司,北京 100053)
4(北京中電普華信息技術(shù)有限公司,北京 100085)
5(國網(wǎng)江蘇省電力公司通信分公司,南京 210008)
在多線程并發(fā)測試需求面前,Junit和TestNG這兩個簡單的單元測試框架一直被拿來作比較,而用戶一般更偏向于配置簡單、靈活、易操作且滿足測試要求的測試框架.本文對Junit和TestNG兩種多線程并發(fā)測試方式進行實驗對比,目的在于驗證兩種框架對多線程并發(fā)測試的實現(xiàn)方式,為用戶在實際測試場景中選擇工具提出了依據(jù).
多線程;并發(fā)測試;JUnit;TestNG
隨著社會的信息化氣味越來越濃重,催促著IT業(yè)的快速發(fā)展,軟件的需求已經(jīng)融入各個行業(yè),用來輔助業(yè)務(wù)的信息化,規(guī)范化和正規(guī)化發(fā)展.軟件的測試技術(shù)將首先解決軟件開發(fā)過程的各種問題,而軟件單元測試在編碼完成后用來對軟件接口等方法進行驗證,是整個軟件生命周期中一個必不可少的環(huán)節(jié),降低軟件使用過程中的出錯率[1].軟件開發(fā)人員更喜歡在軟件投入集成測試前進行自我驗證,減少軟件的缺陷,但這其實更是一個理所應(yīng)當?shù)牟襟E,后面進行集成測試或者系統(tǒng)測試的測試人員都不會花時間去測試一個編碼本身都存在問題的軟件.
大多數(shù)的在單元測試主要由開發(fā)人員來進行,一般主要包括五個方面的測試任務(wù):邊界條件測試、模塊中所有獨立路徑測試、模塊的各條錯誤處理通路測試、局部數(shù)據(jù)結(jié)構(gòu)測試、模塊接口測試[2].這些測試任務(wù)中涉及到的代碼覆蓋率、重復(fù)率、并發(fā)性等問題,促使一些優(yōu)秀自動化測試框架產(chǎn)品的誕生,方便了開發(fā)人員的單元測試工作.目前比較常用的自動化測試框架有C++的CppUnit、CXXTest,Java的Junit、TestNG等[3-5].針對JAVA語言開發(fā)的軟件單元測試,Junit和TestNG在集成開發(fā)工具Eclipse中提供了插件的支持,受到很開發(fā)人員的喜愛,它提高了單元測試的效率,大大節(jié)約的開發(fā)人員編寫測試用例的時間,通過最后測試分析,更容易發(fā)現(xiàn)編碼當中存在缺陷[6-11].
在最新的Junit版本Junit4中已經(jīng)不需要測試方法以Test開頭,不用再繼承TestCase類等,同時此版本提供了注解,注解的使用簡化的測試用例的代碼量,提高測試的效率,但Junit4本身支持多線程并發(fā)測試,卻沒有提供的相應(yīng)注解,相比Junit4,TestNG在多線程測試方面則提供了相應(yīng)的注解.最簡單的方式是在要測試的方法前加上注解,如:
@Test(threadPoolSize=10,invocationCount=3, timeOut=1000),通 過 在 @Test注 解 中 配 置threadPoolSize這個屬性來進入多線程模式的.屬性threadPoolSize的值代表該測試方法將會在10個不同的線程中同時執(zhí)行,屬性invocationCount配置的是該測試方法將被執(zhí)行的總次數(shù),timeOut的值將規(guī)定每次執(zhí)行該測試方法所耗費時間的閾值,超時則測試失敗[12-14],這是最簡單的方法級別的多線程配置.
1.1 Junit多線程簡介
對于傳統(tǒng)的測試方式,大家都會使用main方法來執(zhí)行測試的方法,對于要執(zhí)行多線程的方法,創(chuàng)建一個線程類,再循環(huán)執(zhí)行線程類,以此來做到測試多線程并發(fā).Junit4支持通過在要進行測試多線程的類前加上注解:@RunWith(TestRunner.class),TestRunner是自定義的類,繼承了BlockJUnit4ClassRunner,而擴展的TestRunner內(nèi)部則實現(xiàn)了對多線程的定義,使得加上了該注解的類按TestRunner中的實現(xiàn)來跑多線程.
盡管Junit4對比之前幾個版本的Junit,最大的一個亮點是提供了注解,方便很多測試需要,但遺憾的是沒有提供多線程并發(fā)測試的注解.而TestNG則彌補了Junit的不足,支持的多線程并發(fā)測試的XML配置.
1.2 TestNG多線程簡介
TestNG支持在多線程環(huán)境中執(zhí)行的測試方法,這種靈活的配置只需在所需測試的方法前加上一個注解,如 前 面 介 紹 的 @Test(threadPoolSize = 10, invocationCount=3,timeOut=1000),不僅如此,通過XML的配置,TestNG更能支持并行執(zhí)行測試方法,測試類,測試組件.testng.xml文件的節(jié)點屬性parallel可以設(shè)置多線程并發(fā)運行測試的類型,屬性thread-count可以設(shè)置并發(fā)執(zhí)行時的線程池數(shù)量.
相對于傳統(tǒng)的單線程執(zhí)行測試的方式,這種多線程方式擁有很大的優(yōu)勢,由于是并發(fā)測試,總體測試的運行時間則可以大大減少,并且可以單獨驗證某段代碼在多線程環(huán)境中運行的正確性.
2.1 Junit4多線程實現(xiàn)
2.1.1 通過main方法實現(xiàn)多線程
現(xiàn)在我們用傳統(tǒng)的main方法來執(zhí)行線程,首先設(shè)計一個類,其中有兩個待測試的方法,方法的內(nèi)容都是打印出一行信息,打印的信息后面拼接一個線程ID,主要代碼如表1所示.
表1 Junit測試類設(shè)計代碼
通過表1的代碼,我們可以知道測試類JunitA中有兩個方法junitAMethodOne和junitAMethodTwo,這兩個方法前面標注了@Test,說明兩個方法是要借助Junit框架進行測試的方法.在方法的內(nèi)部,做的主要工作就是打印出一句信息,如:System.out.println ("junitAMethodOne"+id),打印的信息拼接了一個線程ID,此線程ID可以幫助我們知道該方法是被哪個線程所執(zhí)行.線程ID的線程的標識,通過它我們就能判斷兩個方法是在不同的線程中執(zhí)行還是在同一個線程中執(zhí)行.
設(shè)計好測試類后,通過在另一個擁有main方法的類中來測試上述的兩個方法,主要代碼如表2所示.在mian方法中使用循環(huán)來開啟多個線程Thread,這里開啟了2個線程.線程run方法是執(zhí)行任務(wù)的地方,這里使用JUnitCore.runClasses來執(zhí)行要測試的類,這樣會以線程模式來運行測試類中所有標注了@Test的方法.JUnitCore是執(zhí)行所有測試類的核心入口類,通過JUnitCore調(diào)用runClassses()方法,傳遞一個我們要進行的測試類數(shù)組,數(shù)組有一個值,即JunitA.class,運行后,將會有2個線程來并發(fā)執(zhí)行測試類JunitA中的兩個方法.
表2 main方法內(nèi)部主要代碼
運行表2中的代碼得到如表3所示的運行結(jié)果,從表3的運行結(jié)果可以看出,有兩個線程ID分別為8和9的線程執(zhí)行了測試類JunitA中的方法,線程8執(zhí)行后打印出:junitAMethodOne 8和junitAMethodTwo 8;線程 9執(zhí)行后打印出:junitAMethodOne 9和junitAMethodTwo 9.
表3 通過main方法運行結(jié)果
2.1.2 自定義Runner實現(xiàn)多線程
Junit4框架中引入了擴展的機制,它允許我們通過自定義Runner來個性化我們自己的測試需求.Junit中的測試用例是交由Runner去執(zhí)行的,所以擴展這個Runner,我們也達到多程線并發(fā)測試需求.默認情況下Junit4使用BlockJUnit4ClassRunner,在開發(fā)我們自己的Runner類時,需要繼承BlockJUnit4ClassRunner,自定義Runner類關(guān)鍵代碼如表4所示.
表4 自定義Runner類
private final FrameworkMethod method; private final RunNotifier notifier; @Override public void run() { MultiThreadedRunner.super.runChild(method,notifier);//通過參數(shù)method的傳遞運行測試類的方法numThreads.decrementAndGet(); } } } }
從表 4代碼可以看出,自定義的MultiThreadedRunner內(nèi)部嵌套了一個實現(xiàn)了Runnable接口的內(nèi)部類,而這個內(nèi)部類是實現(xiàn)多程線的關(guān)鍵,通過實現(xiàn) Runnable接口中的 run方法來執(zhí)行MultiThreadedRunner的runChild方法,runChild是執(zhí)行測試類的測試方法,在該方法中,由變量thread_count控件著啟動線程的個數(shù),這里設(shè)置為4,然后通過new Thread(new Test(method,notifier)).start()運行線程,從而做到多線程并發(fā)測試的目的,所以內(nèi)部關(guān)鍵代碼其實和通過main方法的實現(xiàn)方式是類似的,只是自定義的Runner類如何運用于測試類呢?
擴展了Runner后,在要進行測試的JunitA類前加上 注 解 @RunWith(MultiThreadedRunner.class),則JunitA運行時會使用MultiThreadedRunner來跑多線程.其運行結(jié)果如表5所示.
表5 通過自定義Runner運行結(jié)果
從表5的運行結(jié)果可以看出,此方式只針對測試類的第一個方法運行多線程并發(fā)測試,因此對于實際業(yè)務(wù)測試過程中需要對某個特定的重要接口進行多線程并發(fā)測試可以使用此方式,只要設(shè)置好thread_count變量的值,可以任意進行測試.
2.2 TestNG多線程實現(xiàn)
TestNG的多線程一直是開發(fā)人員在執(zhí)行方法并發(fā)測試時的首選,基于XML文件的配置簡單,靈活,容易上手,滿足的場景多樣性,而且TestNG的多線程并發(fā)測試是安全的,XML配置文件的結(jié)構(gòu)圖如圖1所示.
圖1 XML多線程配置文件結(jié)構(gòu)圖
表6說明了XML涉及多線程配置時各節(jié)點的意義.通過在XML文件中的相關(guān)節(jié)點的配置,我們可以只對一個類中的所有方法進行并發(fā)測試;對多個類進行并發(fā)測試;對同一個測試套件內(nèi)的多個測試組件進行并發(fā)測試.
表6 XML多線程配置文件屬性節(jié)點說明
接下來我們運用TestNG通過基于XML的配置方式來實現(xiàn)對測試類的多線程實現(xiàn)設(shè)計.首先設(shè)計一個測試類TestngA,類中有兩個待測試的方法,方法的內(nèi)容都是打印出一行信息,打印的信息后面拼接一個線程ID,主要代碼如表7所示.
表7 TestNG測試類設(shè)計代碼
public void testngAMethodTwo(){ long id=Thread.currentThread().getId();/獲取一個線程ID System.out.println("testngAMethodTwo"+id);//方法二打印帶有線程ID的一條信息} }
2.2.1 并發(fā)執(zhí)行測試方法
現(xiàn)在我們通過基于XML文件的配置方式來測試多線程的并發(fā)測試實驗.并發(fā)執(zhí)行測試類中的所有測試方法對應(yīng)的XML配置文件如表8所示.
表8 并發(fā)測試方法的XML文件配置
從表8中我們看到suite這個節(jié)點有個parallel屬性設(shè)置成了“methods”,它代表TestNG將在不同的線程內(nèi)運行測試方法.“thread-count”代表啟用的線程個數(shù),此處設(shè)置成2,代表將有2個線程被分配來執(zhí)行測試方法.因此針對測試類TestngA中的兩個方法,將會在2個不同的線程內(nèi)被執(zhí)行.
通過右擊此XML配置文件,選擇Run as->TestNG Suite,可以看到運行結(jié)果如表9所示,從輸出結(jié)果后面拼接的線程ID可以看出,2個方法是在不同的線程內(nèi)執(zhí)行的.
表9 TestNG并發(fā)執(zhí)行測試方法的運行結(jié)果
2.2.2 并發(fā)執(zhí)行測試類
由于本節(jié)要以多線程的模式并發(fā)執(zhí)行測試類,因此需要再設(shè)計一個測試類TestngB,該類也有兩個測試方法:testngBMethodOne和testngBMethodTwo,其它和測試類TestngA相同,方法內(nèi)部也是打印出帶有線程ID的信息.現(xiàn)在修改上節(jié)的XML配置文件,使它能夠在測試類之間并發(fā)執(zhí)行,修改后的XML配置文件如表10所示.
表10 并發(fā)測試類的XML文件配置
對比表8的配置文件,我們可以看出,唯一不同的是為滿足并發(fā)執(zhí)行測試類,需要在classes節(jié)點下再增加要并發(fā)執(zhí)行的測試類的信息,我們在本例中配置了TestngA和TestngB兩個測試類,運行后的結(jié)果如表11所示.
表11 TestNG并發(fā)執(zhí)行測試類的運行結(jié)果
從表11的運行結(jié)果可以看出,TestngA的方法testngAMethodOne和TestngB的方法testngBMethodOne是在線程9內(nèi)執(zhí)行的,而TestngA的方法testngAMethodTwo和TestngB的方法testngBMethodTwo是在線程10內(nèi)執(zhí)行的,也就是說TestngA和TestngB兩個測試類是并發(fā)被執(zhí)行的.
2.2.3 并發(fā)執(zhí)行測試組件
XML配置文件的test節(jié)點是用來配置測試組件,前面2節(jié)的配置文件中,測試類都是配置在同一個名為“test1”測試組件中的,現(xiàn)在我們修改XML配置文件,將 TestngA分配在名為“test1”的測試組件中,將TestngB分配在名為“test2”的測試組件中,修改后的XML配置文件如表12所示.
表12 并發(fā)執(zhí)行測試組件的XML文件配置
運行表12的配置文件得到的運行結(jié)果如表13所示.
表13 TestNG并發(fā)執(zhí)行測試組件的運行結(jié)果
從表13的運行結(jié)果可以看出,雖然配置文件中thread-count設(shè)置成2,表示用2個線程來運行兩個測試組件,但對于TestngA和TestngB中的2個方法, TestNG又分別分配了2個不同的進程來執(zhí)行.由此得到的結(jié)論是,不同的組件中的測試類TestNG保證了它們在獨立的進程中執(zhí)行,同時根據(jù)suite節(jié)點中的thread-count屬性的設(shè)置分配了所設(shè)置個數(shù)的線程數(shù)量來運行各個測試組件中的測試方法.
2.3 JUnit和TestNG對比分析
通過實驗得出的基于多線程并發(fā)測試的JUnit和TestNG兩種測試框架的技術(shù)對比結(jié)果如表14所示.
表14 多線程并發(fā)的JUnit和TestNG框架對比
從表14的框架對比內(nèi)容可以看出,兩種測試框架中都可以達到大家的多線程并發(fā)測試的需求,Junit通過main方法或者自定義的Runner來運行測試方法,方法內(nèi)部都是執(zhí)行定義的線程類達到并發(fā)測試; TestNG則更加方便的提供了方法級的注解以及簡單的XML配置,就可以輕松并發(fā)測試,同時無需再去通過編代碼來達到目的.
執(zhí)行并發(fā)測試時,Junit相比TestNG來說,更多的是我們在控制著執(zhí)行的代碼,TestNG則相對偏于配置的組合,一個簡單的XML配置文件便能撐起整個并發(fā)測試的需求.因此結(jié)合這幾個點來說,TestNG在多線程并發(fā)測試方面的優(yōu)勢則比Junit更為突出.
在java單元測試方面,JUnit和TestNG一直是開發(fā)人員最常用的開源自動化測試框架,兩者各有不同的特性,而TestNG則優(yōu)于JUnit,TestNG創(chuàng)建的靈感來自于JUnit和NUnit,但它卻不是一個JUnit的擴展.從支持多程線方面,可以看出,JUnit不管是否實現(xiàn)自定義的Runner,還是從傳統(tǒng)的定義線程類開始,都需要用戶手動編寫代碼來達到測試的目的,同時對特殊場景,還得考慮它的線程安全問題;TestNG基于XML配置的方式來運行多線程或者通過方法級上的注解便可支持多種并發(fā)測試的需求,而且配置文件簡單、靈活、方便,無需用戶多花時間研究它的代碼即可進行測試.所以在進行多線程并發(fā)測試方面,選擇TestNG單元測試框架將是一個正確的決定.
在其他測試需求方面,TestNG還有JUnit框架無法比擬的優(yōu)點,但兩者都有自己適用的場景,開發(fā)人員最需要的是選擇一個適用自己場景的單元測試框架,選擇最合適的會比選擇功能最多的給用戶帶來更意想不到的結(jié)果,靈活的運用測試框架才會完成高效的測試工作.
1周瑞陽,王猛.基于三層體系結(jié)構(gòu)的單元測試框架研究與實現(xiàn).計算機應(yīng)用,2010,30(8):29–37.
2白凱,崔冬華.基于JUnit自動化單元測試的研究.計算機與數(shù)字工程,2010,38(2):52–54.
3孔亮亮,殷兆麟.Java類測試工具JUnit的分析與擴展.計算機工程與設(shè)計,2005,26(12):3413–3416.
4董曉霞.相鄰因素組合測試用例集的最優(yōu)生成方法閉.計算機學(xué)報,2007,30(2):200–210.
5 Denis A,Perez C,Priol T,et al.Padico:A component-based software infrastructure for Grid computing.Proc.of lnternational Parallel and Distributed Processing Symposium. ftp://ftp.inria.fr/INRIA/publication/publi-pdf/RR/RR-4974.pdf. [2010-03-01].
6 Bradley S.Green.Software test automation.ACM,2000,17 (9):9–45.
7 Zhu H,Wong WE,Belli F.Advancing test automation technologyto meet the challenges of model-driven software development.ACM,2008,19(15):5–10.
8 Beust C,Suleiman H.Next generation Java testing:TestNG and advanced concepts.Pearson Education,2007.
9 Wang XC,Xu PJ.Build an Auto Testing Framework Based on Seleniumand FitNesse.2009 International Conference on InformationTechnology and Computer Science.2009,2.436–439.
10余波,王樹林,張大方.基于JUnit自動生成類測試案例框架的實現(xiàn).計算機工程與應(yīng)用,2006,42(10):60–98.
11白凱,崔冬華.基于JUnit自動化單元測試的研究.計算機與數(shù)字工程,2010,38(2):32–35.
12王晶,樊曉婭,張盛兵,等.同時多線程結(jié)構(gòu)的2級調(diào)度策略.西北工業(yè)大學(xué)學(xué)報,2007,(3):433–437.
13肖明清,朱小平,夏銳.并行測試技術(shù)綜述.空軍工程大學(xué)學(xué)報(自然科學(xué)版),2005,(3):22–25.
14夏銳,肖明清,朱小平,等.并行測試技術(shù)在自動系統(tǒng)中的應(yīng)用.計算機測量與控制,2005,13(1):7–10.
Comparison of JUnit and TestNG Testing Framework Based on Concurrent Multi-Thread
WANG Tian-Sheng1,2,MAZhao-Han3,CUI Wei1,LIU Di1,4,ZHAO Jun-Feng5,XIAFei5
1(State Grid Information&Telecommunication Co.Ltd.,Beijing 100761,China)
2(Xiamen Great Power Geo Information Technology Co.Ltd.,Xiamen 361000,China)
3(Great Power Science and Technology Corporation State Grid Information&Telecommunication Group,Beijing100053,China)
4(Beijing China-Power Information Technology Co.Ltd.,Beijing 100085,China)
5(State Grid Jiangsu Electric Power Company&Telecommunication Branch,Nanjing 210008,China)
In front of multi-threaded concurrent test requirements,Junit and TestNG these two simple unit test framework has been used to compare,but users generally prefer to the test framework that configuration is simple, flexible,and easy to operate and satisfied the test requirements.This thesis has made an experimental comparison of Junit and TestNG on multi-threaded concurrent test methods,to verify the two frameworks implementation for multithreaded concurrent test,and provides the basis for the user to select the tool in the actual test scenario for users.
multi-thread;concurrent testing;JUnit;TestNG
2016-09-02;收到修改稿時間:2016-11-07
10.15888/j.cnki.csa.005774