欧美成人午夜免费全部完,亚洲午夜福利精品久久,а√最新版在线天堂,另类亚洲综合区图片小说区,亚洲欧美日韩精品色xxx

軟件白盒測試之Mockito+JMockit+TestNG單元測試實踐總結(jié)

2018-03-05 16:07:10 3586瀏覽

單元測試實踐背景

·測試環(huán)境定位bug時,需要測試同學(xué)協(xié)助手動發(fā)起相關(guān)業(yè)務(wù)URL請求,開發(fā)進行遠程調(diào)試

問題:

1、遠程調(diào)試影響測試環(huán)境數(shù)據(jù)正常獲取,影響測試同學(xué)測試進度

2、遠程調(diào)試代碼有時并非最新代碼,與本地不一致增加調(diào)試難度,往往需要發(fā)最新的包再調(diào)試

3、controller層請求參數(shù)依賴特定客戶端版本發(fā)起,其他版本回歸驗證,增加模擬操作成本

·依賴第三方系統(tǒng),第三方系統(tǒng)請求不穩(wěn)定或希望第三方接口返回特定數(shù)據(jù)



為什么需要單測

編寫單元測試代碼并不是一件容易的事情,那為什么還需要去話費時間和精力來編寫單元測試呢?

減少Bug:如今的項目大多都是多人分模塊協(xié)同開發(fā),當(dāng)各個模塊集成時再去發(fā)現(xiàn)問題,定位和溝通成本是非常高的,通過單元測試來保證各個模塊的正確性,可以盡早的發(fā)現(xiàn)問題,而不時等到集成時再發(fā)現(xiàn)問題。

放心重構(gòu):如今持續(xù)型的項目越來越多,代碼不斷的在變化和重構(gòu),通過單元測試,開發(fā)可以放心的修改重構(gòu)代碼,減少改代碼時心理負擔(dān),提高重構(gòu)的成功率。

改進設(shè)計:越是良好設(shè)計的代碼,一般越容易編寫單元測試,多個小的方法的單測一般比大方法(成百上千行代碼)的單測代碼要簡單、要穩(wěn)定,一個依賴接口的類一般比依賴具體實現(xiàn)的類容易測試,所以在編寫單測的過程中,如果發(fā)現(xiàn)單測代碼非常難寫,一般表明被測試的代碼包含了太多的依賴或職責(zé),需要反思代碼的合理性,進而推進代碼設(shè)計的優(yōu)化,形成正向循環(huán)。

個人感受,將controller層請求參數(shù)抽取管理后,debug不依賴客戶端與測試環(huán)境,能夠迅速在本地執(zhí)行定位問題;同時,單元測試提供測試數(shù)據(jù)準(zhǔn)備與模擬特定測試數(shù)據(jù)返回,對業(yè)務(wù)測試起輔助作用。

單元測試需要理解的幾個概念

被測系統(tǒng):SUT(SystemUnderTest)

被測系統(tǒng)(Systemundertest,SUT)表示正在被測試的系統(tǒng),目的是測試系統(tǒng)能否正確操作。這一詞語常用于軟件測試中。軟件系統(tǒng)測試的一個特例是對應(yīng)用軟件的測試,稱為被測應(yīng)用程序(applicationundertest,AUT)。

SUT也表明軟件已經(jīng)到了成熟期,因為系統(tǒng)測試在測試周期中是集成測試的后一階段。

測試替身:TestDouble

在單元測試時,使用TestDouble減少對被測對象的依賴,使得測試更加單一。同時,讓測試案例執(zhí)行的時間更短,運行更加穩(wěn)定,同時能對SUT內(nèi)部的輸入輸出進行驗證,讓測試更加徹底深入。但是,TestDouble也不是萬能的,TestDouble不能被過度使用,因為實際交付的產(chǎn)品是使用實際對象的,過度使用TestDouble會讓測試變得越來越脫離實際。

要理解測試替身,需要了解一下DummyObjects、TestStub、TestSpy、FakeObject這幾個概念,下面我們對這些概念分別進行說明。

DummyObjects

DummyObjects泛指在測試中必須傳入的對象,而傳入的這些對象實際上并不會產(chǎn)生任何作用,僅僅是為了能夠調(diào)用被測對象而必須傳入的一個東西。

TestStub

測試樁是用來接受SUT內(nèi)部的間接輸入(indirectinputs),并返回特定的值給SUT??梢岳斫釺estStub是在SUT內(nèi)部打的一個樁,可以按照我們的要求返回特定的內(nèi)容給SUT,TestStub的交互完全在SUT內(nèi)部,因此,它不會返回內(nèi)容給測試案例,也不會對SUT內(nèi)部的輸入進行驗證。

TestSpy

TestSpy像一個間諜,安插在了SUT內(nèi)部,專門負責(zé)將SUT內(nèi)部的間接輸出(indirectoutputs)傳到外部。它的特點是將內(nèi)部的間接輸出返回給測試案例,由測試案例進行驗證,TestSpy只負責(zé)獲取內(nèi)部情報,并把情報發(fā)出去,不負責(zé)驗證情報的正確性。

MockObject

MockObject和TestSpy有類似的地方,它也是安插在SUT內(nèi)部,獲取到SUT內(nèi)部的間接輸出(indirectoutputs),不同的是,MockObject還負責(zé)對情報(intelligence)進行驗證,總部(外部的測試案例)信任MockObject的驗證結(jié)果。

FakeObject

經(jīng)常,我們會把FakeObject和TestStub搞混,因為它們都和外部沒有交互,對內(nèi)部的輸入輸出也不進行驗證。不同的是,F(xiàn)akeObject并不關(guān)注SUT內(nèi)部的間接輸入(indirectinputs)或間接輸出(indirectoutputs),它僅僅是用來替代一個實際的對象,并且擁有幾乎和實際對象一樣的功能,保證SUT能夠正常工作。實際對象過分依賴外部環(huán)境,F(xiàn)akeObject可以減少這樣的依賴。

看完TestDouble這幾個概念后,是不是一頭霧水?以下通俗解釋,DummyObjects就不做解釋了。

TestStub

系統(tǒng)測試需要某一指定數(shù)據(jù)返回時,開發(fā)將獲取數(shù)據(jù)邏輯代碼替換成指定數(shù)據(jù),發(fā)包測試完再替換回原來邏輯。替換代碼返回指定數(shù)據(jù),這就是測試樁。

TestSpy

TestStub只返回指定內(nèi)容給SUT,并沒有指定返回測試案例,所以我們引入單元測試,在單元測試用例調(diào)用引用該插樁的方法。

這時我們能獲測試樁間接輸出內(nèi)容,甚至是報錯信息,再也不用到服務(wù)器查找錯誤日志了,這就是TestSpy。

MockObject

MockObject就是在TestSpy的基礎(chǔ)上,加入驗證機制。調(diào)用引用該插樁的方法,我們要確保這個插樁正常被執(zhí)行或指定執(zhí)行n次,得到的結(jié)果是不是我們期望的結(jié)果,mock就以此為生。

FakeObject

FakeObject相對TestStub,是一個面向?qū)ο蟾拍?。我們只希望替換掉一個實際被引用對象里面的一個方法返回值,被替換某個方法返回值的對象就叫FakeOject,它與實際對象一樣的功能。MockObject也囊括FakeObject概念,可以看出TestStub<FakeObject<MockObject。

Mock框架模型

測試驗證過程,我們不可能每次都修改代碼stub一個方法,發(fā)包驗證完后再改回,發(fā)布外網(wǎng)回歸驗證階段這種操作根本不被允許。Mock框架應(yīng)運而生,我們在單元測試用例stub一個方法后,將之注入被測系統(tǒng)SUT,這個注入只會在testspy階段產(chǎn)生影響。

市面上很多mock框架,Jmockit、Mockito、PowerMock、EasyMock等,大體遵循record-replay-verify模型設(shè)計,有些地方稱之為expect-run-verify模式(期望--運行--驗證),有些地方稱之(AAA階段)Arrange、Act、Assert,大體一個意思。很明顯,Mock框架的應(yīng)用過程,我們先需要指定stub,然后運行被測方法,然后在驗證stub的正確性,這個過程就稱之為mock。

單元測試框架選擇

Testng

TestNG與Junit很相似,但testng更加靈活,以下為兩者對比。

[圖片上傳失敗...(image-93566-1513052813178)]

參考JUnit4VsTestNG比較

·Testng支持分組測試

·Testng參數(shù)化測試支持復(fù)雜類型參數(shù),而junit只支持基本類型

·Testng提供XML靈活配置測試運行套件

·Testng支持依賴測試

·Testng支持并發(fā)測試,上面文章未講到的,補充下。如@Test(threadPoolSize=3,invocationCount=6,timeout=500),而Junit的話可以引入JunitPref框架。

Jmockit

Jmockit是一個功能很強大的框架,可以mock靜態(tài)方法、final類、抽象類、接口、構(gòu)造函數(shù)等,幾乎無所不能,但編程語言不夠簡潔。

Jmockit的介紹和使用

這里需要補充的點:

·注解@Tested,標(biāo)識的被測對象實例,@Injectable的實例會自動注入到@Tested中,有時候在事件過程中實在無法注入,可以借助spring的反射工具ReflectionTestUtils進行注入。

·Expectations:期望,指定的方法必須被調(diào)用,且方法默認次數(shù)為1。如果指定打樁的方法在test用例不被調(diào)用,或者調(diào)用次數(shù)超過1,則會報錯,建議使用NonStrictExpectations配合Verifications使用。

·Expectations(T)/NonStrictExpectations(T),Expectations(.class){}這種方式只會模擬區(qū)域中包含的方法,這個類的其它方法將按照正常的業(yè)務(wù)邏輯運行,T就變成了一個FakeObject。

·MockUp(T)中,未mock的函數(shù)不受影響,T也是一個FakeObject。通常rpc接口(接口無具體實現(xiàn)方法)、構(gòu)造函數(shù)通過MockUp進行局部方法mock。

以下主要演示一個rpc接口的mock。

publicclassColumnArticlesControllerTest2extendsBaseContorllerMockTest{

privateMockMvcmockMvc;

@Autowired

privateConfigServiceconfigService;

@Autowired

privateICpDataKievHandlercpDataKievHandler;

@Autowired

privateIndexArticlesDaoCacheImplindexArticlesDao;

@Autowired

privateColumnArticlesControllercolumnArticlesController;

@BeforeMethod()

publicvoidsetUp()throwsException{

mockMvc=MockMvcBuilders.standaloneSetup(columnArticlesController).build();

}

//CSV最好使用gbk格式,目前不支持默認路徑,CSV文件位于到dataprovider目錄下

@Test(description="測試list.do接口",dataProvider="genData",dataProviderClass=CommonDataProvider.class)

@Csv("/dataprovider/ColumnArticlesControllerTest/testGetColumnArticleList.csv")

publicvoidtestGetColumnArticleList(StringcpChannelId,longcolumnId,StringucParam,Integerv,Stringflymeuid,

Stringnt,Stringvn,Stringdeviceinfo,StringdeviceType,Stringos,IntegersupportSDK,IntegercpType)

throwsException{

Stringimei=deviceinfo.substring(deviceinfo.indexOf("imei="),deviceinfo.indexOf("&"));

ArticleViewparams=newArticleView();

params.setCpChannelId(cpChannelId);

params.setColumnId(columnId);

params.setUcparam(ucParam);

params.setClientReqId(System.currentTimeMillis()+imei);

CommonParamscommonParams=newCommonParams();

commonParams.setV(v);

commonParams.setFlymeuid(flymeuid);

commonParams.setNt(nt);

commonParams.setVn(vn);

commonParams.setDeviceinfo(DeviceUtil.deviceToEncrypt(deviceinfo));

commonParams.setDeviceType(deviceType);

commonParams.setOs(os);

System.out.println(configService.getConfigValue(ConfigKeyEnum.UC_VIDEO_PER));

//jmock靜態(tài)方法mock掉ip,防止http請求獲取Ip報錯

newNonStrictExpectations(WebUtils.class,configService){

{

WebUtils.getClientIp();

result="172.17.132.66";

}

{

//后臺控制百分比,返回0則過濾掉類型為27的視頻,返回100則放開下發(fā)該視頻“XXX鍵盤”

configService.getConfigValue(ConfigKeyEnum.UC_VIDEO_PER);

result="100";

}

};

finalICpDataKievHandlercpDataKievHandler2=cpDataKievHandler;

try{

Stringvideo27Articles=FileUtils

.getFileText(FileUtils.getCurrentProjectPath()+"/src/test/resources/afdata/video27Articles.json");

finalCpDataResultvalue=JSON.parseObject(video27Articles,CpDataResult.class);

cpDataKievHandler=newMockUp<ICpDataKievHandler>(){

@mockit.Mock

CpDataResultgetUCArticleList(Stringimei,longchannelId,Stringmethod,Stringrecoid,longftime,

StringcityCode,StringcityName,intpageSize){

returnvalue;

}

}.getMockInstance();

ReflectionTestUtils.setField(indexArticlesDao,"cpDataKievHandler",cpDataKievHandler);

System.out.println(JSON

.toJSON(columnArticlesController.getColumnArticleList(params,supportSDK,cpType,commonParams)));

}finally{

//mock完還原接口方法取值,避免影響其他用例

ReflectionTestUtils.setField(indexArticlesDao,"cpDataKievHandler",cpDataKievHandler2);

}

}

以上就是關(guān)于扣丁學(xué)堂軟件測試培訓(xùn)之Mockito+JMockit+TestNG單元測試實踐總結(jié)的詳細介紹,最后想要了解更多關(guān)于軟件測試培訓(xùn)發(fā)展前景趨勢,請關(guān)注扣丁學(xué)堂官網(wǎng)、微信等平臺,扣丁學(xué)堂IT職業(yè)在線學(xué)習(xí)教育平臺為您提供權(quán)威的軟件測試視頻教程系統(tǒng),通過千鋒扣丁學(xué)堂金牌講師在線錄制的軟件測試在線視頻教程,讓你快速掌握軟件測試從入門到精通開發(fā)實戰(zhàn)技能。



扣丁學(xué)堂微信公眾號



關(guān)注微信公眾號獲取更多學(xué)習(xí)資料



查看更多關(guān)于“軟件測試技術(shù)資訊的相關(guān)文章>>

標(biāo)簽: 軟件測試培訓(xùn) 軟件測試工程師 軟件測試在線視頻 軟件測試視頻教程 軟件測試教程 白盒測試 黑盒測試

熱門專區(qū)

暫無熱門資訊

課程推薦

微信
微博
15311698296

全國免費咨詢熱線

郵箱:codingke@1000phone.com

官方群:148715490

北京千鋒互聯(lián)科技有限公司版權(quán)所有   北京市海淀區(qū)寶盛北里西區(qū)28號中關(guān)村智誠科創(chuàng)大廈4層
京ICP備2021002079號-2   Copyright ? 2017 - 2022
返回頂部 返回頂部