基于testNG的数据驱动测试的自动化测试实践(一)
歷時(shí)4個(gè)月,從搭建測(cè)試框架到給全員培訓(xùn),再到最終團(tuán)隊(duì)內(nèi)落地,最終效果是整個(gè)團(tuán)隊(duì)QA測(cè)試階段效率提升60%多。既然有數(shù)據(jù)就有衡量標(biāo)準(zhǔn),統(tǒng)計(jì)了近2個(gè)月的開發(fā)階段/測(cè)試階段的耗時(shí)比,比如自動(dòng)化前,開發(fā)階段/測(cè)試階段耗時(shí)比2:1,如今達(dá)到5.3:1,簡(jiǎn)單說開發(fā)5人天,測(cè)試原來花費(fèi)2.5人天,現(xiàn)在花費(fèi)1人天,當(dāng)然這是平均值。這不僅是單單自動(dòng)化測(cè)試框架的搭建,還需要配合管理手段,如何將自動(dòng)化測(cè)試不單單用于回歸測(cè)試而是整個(gè)QA測(cè)試,何時(shí)寫用例?何時(shí)寫腳本?何時(shí)執(zhí)行腳本?如何維護(hù)腳本?如何給全員培訓(xùn)?(大家代碼基礎(chǔ)很薄弱,降低學(xué)習(xí)成本,快速上手很關(guān)鍵)這一整套的配合才能更好的將自動(dòng)化測(cè)試落地。
整個(gè)自動(dòng)化測(cè)試框架搭建經(jīng)歷了2個(gè)階段。
第一個(gè)階段:從0到1,提高效率,耗時(shí)3個(gè)月,主要目標(biāo)是框架分層以及70多個(gè)API接口的幾百個(gè)場(chǎng)景的覆蓋,效果就是上面提到效率提高60%
第二個(gè)階段:核心框架重構(gòu)和API接口遷移,耗時(shí)1個(gè)月,主要目標(biāo)是降低維護(hù)和學(xué)習(xí)成本,通過1,2次培訓(xùn),可以上手做自動(dòng)化測(cè)試。同時(shí)將被測(cè)的API接口遷移至新的框架,最終代碼量降低了90%,腳本執(zhí)行時(shí)間提高了95%。
框架的作用?
把自動(dòng)化測(cè)試框架比喻成搭積木吧,核心框架的搭建,工具類的封裝類似于積木塊,按照一定規(guī)則寫符合各業(yè)務(wù)需求的用例腳本類似于搭積木,搭積木學(xué)習(xí)成本較低,只要培訓(xùn)就能上手,按照工具類的方法正確使用,按照框架的層級(jí)要求正確拼裝,可以使整個(gè)團(tuán)隊(duì)內(nèi)自動(dòng)化測(cè)試快速落地。
- 積木塊:
分層大致是 ? ?java--base包 ? ? 作用:獲取接口信息并調(diào)用接口,ps:具體的接口地址,名稱,基礎(chǔ)入?yún)⒋鎯?chǔ)于數(shù)據(jù)庫(kù)里
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? --driver包 ? 作用:工具類和selenium驅(qū)動(dòng),包含入?yún)㈥P(guān)鍵詞,接口斷言,數(shù)據(jù)庫(kù)操作等
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? --operation包 ? 作用:基于 web driver的UI自動(dòng)化基礎(chǔ)操作
以上部分由專人維護(hù),根據(jù)業(yè)務(wù)需要不斷補(bǔ)充接口和工具類
- 搭積木
? ? ? ? ? ? ? ? ? ? ? ?test--autocase包--bvt? ?作用:冒煙測(cè)試范圍的用例腳本,用于回歸測(cè)試
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?--api ? ?作用:所有功能測(cè)試的用例腳本,用于日常功能測(cè)試
這一部分由業(yè)務(wù)測(cè)試人員維護(hù),根據(jù)各自負(fù)責(zé)的需求編寫對(duì)應(yīng)的測(cè)試腳本,90%以上覆蓋手工用例。
對(duì)于業(yè)務(wù)人員如何寫腳本呢?以一個(gè)BVT級(jí)別的腳本為例,測(cè)試發(fā)紅包-搶紅包-退紅包的場(chǎng)景,整個(gè)流程需要6個(gè)接口。
腳本分為6步:發(fā)紅包-發(fā)紅包查詢-搶紅包-搶紅包查詢-退紅包-退紅包查詢。
發(fā)紅包分為綁卡支付,余額支付2種,退款紅包又分為原路退回和退回到余額。針對(duì)不同的場(chǎng)景,進(jìn)行組合,會(huì)有4種場(chǎng)景,而腳本的流程是相同的,采用testNG的DataProvider可以參數(shù)化,只需要增加測(cè)試數(shù)據(jù),每個(gè)測(cè)試數(shù)據(jù)對(duì)應(yīng)一個(gè)用例,隨著用例的增加不會(huì)顯性增加代碼數(shù)量,大多情況下只需要維護(hù)好數(shù)據(jù)即可。
為了更加清晰,測(cè)試數(shù)據(jù)分為3部分{ ?用例名稱,入?yún)?#xff0c;斷言},當(dāng)然這是比較標(biāo)準(zhǔn)的情況,根據(jù)實(shí)際接口可以靈活變通。最后腳本如下:
@DataProvider(name = "redpacket_bvt")public Object[][] redpacket_bvt_parm(){return new Object[][]{{"*發(fā)紅包-綁卡,搶紅包,原路退回**","BINDCARD","OLDWAY","{'code':'QM000000','message':'受理成功'}"},{"*發(fā)紅包-綁卡,搶紅包,退回余額**","BINDCARD","BALANCE","{'code':'QM000000','message':'受理成功'}"},{"*發(fā)紅包-余額支付,搶紅包,原路退回**","BALANCE","OLDWAY","{'code':'QM000000','message':'受理成功'}"},{"*發(fā)紅包-余額支付,搶紅包,退回余額**","BALANCE","BALANCE","{'code':'QM000000','message':'受理成功'}"},};} /*** 發(fā)紅包-搶紅包-退紅包* @throws Exception*/@Test(dataProvider ="redpacket_bvt" )public void redpacket_bvt(String name,String payTool,String refundWay,String assertjson) throws Exception{System.out.println(name);//發(fā)紅包String replacejsonA="{'orderAmount':'0.02','merchantUserId':'"+huiyuanA+"','payTool':'"+payTool+"','bindId':'"+A_bindid+"'}";String resultA = YopApiRedpacket.redpacket_consume(merchant,replacejsonA);ToolUtils.AssertEqualfromJson(resultA, assertjson);ToolUtils.AssertExist(resultA, "requestNo,redOrderNo,orderAmount");TimeUnit.SECONDS.sleep(2);//發(fā)紅包查詢String replacejsonB="{'sendRequestNo':'"+ToolUtils.getJsonValue(resultA, "requestNo")+"'}";String resultB = YopApiRedpacket.redpacket_order_query(merchant,replacejsonB);ToolUtils.AssertEqualfromJson(resultB, assertjson);ToolUtils.AssertExist(resultB, "total,trxTime,effectiveTime,redOrderNo,state,fromUserNo,lastAmount");//搶紅包String replacejsonC = "{'trxAmount':'0.01','merchantUserId':'"+huiyuanA+"','redOrderNo':'"+ToolUtils.getJsonValue(resultB, "redOrderNo")+"'}";String resultC = YopApiRedpacket.redpacket_grab(merchant,replacejsonC);ToolUtils.AssertEqualfromJson(resultC, assertjson);ToolUtils.AssertExist(resultC, "requestNo,redOrderNo,grabOrderNo");//搶紅包查詢String replacejsonD = "{'grabRequestNo':'"+ToolUtils.getJsonValue(resultC, "requestNo")+"'}";String resultD = YopApiRedpacket.redpacket_grab_query(merchant,replacejsonD);ToolUtils.AssertEqualfromJson(resultD, assertjson);ToolUtils.AssertExist(resultD, "requestNo,redOrderNo,grabOrderNo,amount,ppMerchantNo,toUserNo,status,grabTime");//退紅包String replacejsonE = "{'redOrderNo':'"+ToolUtils.getJsonValue(resultC, "redOrderNo") +"','refundWay':'"+refundWay+"'}";String resultE = YopApiRedpacket.redpacket_refund(merchant, replacejsonE);ToolUtils.AssertEqualfromJson(resultE, assertjson);ToolUtils.AssertExist(resultE, "requestNo,redOrderNo,refundAmount");TimeUnit.SECONDS.sleep(2);String replacejsonF = "{'redOrderNo':'"+ToolUtils.getJsonValue(resultE, "redOrderNo")+"'}";String resultF = YopApiRedpacket.redpacket_refund_query(merchant, replacejsonF);ToolUtils.AssertEqualfromJson(resultF, assertjson);ToolUtils.AssertExist(resultF, "requestNo,redOrderNo,refundWay,ppMerchantNo,refundAmount,merchantUserId,status,createTime,updateTime,refundTime");}入?yún)⒓记?#xff1a;
1、保存一組基礎(chǔ)入?yún)?#xff0c;比如一個(gè)接口有5個(gè)字段,3個(gè)必填項(xiàng),2個(gè)非必填。那么3個(gè)必填項(xiàng)是基礎(chǔ)入?yún)?#xff0c;存在數(shù)據(jù)庫(kù)里,2個(gè)非必填根據(jù)用例需要在業(yè)務(wù)層測(cè)試數(shù)據(jù)傳入。
2、無論是不是必填項(xiàng),根據(jù)用例場(chǎng)景需要變化的入?yún)⒃跇I(yè)務(wù)層傳入,沒有傳入的取自數(shù)據(jù)庫(kù)的基礎(chǔ)入?yún)?#xff0c;這樣可以減少測(cè)試數(shù)據(jù)的維護(hù)成本。
3、定義一些關(guān)鍵詞,比如隨機(jī)數(shù),當(dāng)前日期等等,看業(yè)務(wù)需要,作用就不多說了,做過自動(dòng)化基本都知道。
| @random | 隨機(jī)字符串10位 | txt@random = txt1234567890 |
| @date | 當(dāng)前時(shí)間 | @date = yyyy-MM-dd HH:mm:ss |
| @merchant | 所選測(cè)試錢麥商編,如1247 | @merchant = BM12345678901247 |
?
4、入?yún)⒏袷?#xff1a;統(tǒng)一json形式傳遞。
{"requestNo":"redf@random","orderAmount":"0.02","merchantOrderDate":"@date","merchantExpireTime":"","serverCallbackUrl":"@serverCallbackUrl","merchantUserId":"qianmai3610","payTool":"BINDCARD","totalNumber":"2","bindId":"262531657","userIp":"10.1.1.1" }?
?
? ??
?
?
? ??
?
總結(jié)
以上是生活随笔為你收集整理的基于testNG的数据驱动测试的自动化测试实践(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 新浪体育——篮球足球的直播和战报爬取
- 下一篇: 8.4|Crypto Tech Nigh