接口入参形式_花椒测试平台 接口篇
背景
先來說說花椒測試平臺的由來:
目的1,降低接口測試對測試人員代碼能力的要求。測試人員只需要知道接口的url,請求參數,以什么樣的格式傳個服務端,接口的響應數據里需要驗證哪個字段的值即可進行測試,而不需要知道怎么建一個工程,怎么建一個測試類,測試方法,testng是怎么使用的,結果怎么解析,怎么取到想要的字段去做判斷。
目的2,可視化的case管理,執行,結果管理。打開一個瀏覽器,根據接口文檔新建一個測試case,執行檢查接口返回,保存case,建不同入參的該接口的case,組成case集,批量運行,查看運行結果,相比于工程執行批量case,testng的html結果,平臺的集中展示更清晰。
既然接口的測試已經有case的信息了,對接口進行壓測的請求其實也類似一個case,只不過是有很多人在同時執行這個case,所以有了壓力測試和接口測試平臺的整合。在平臺建壓測任務的時候選定一個測試用例為載體,多并發的執行case,統計壓測數據,實時展示。以往接口測試和壓力測試都是分別寫一個方法,里面有很多重復的部分。
接下來我們會想,像接口測試是由數據驅動的,那么UI自動化是否可以理解為一種另類的驅動呢?UI操作的公共方法如點擊,輸入,檢查元素的值,其實和接口入參和結果檢查很像,基于cucumber我們將UI自動化集成進了測試平臺,測試人員只需要關心我點擊的是哪個頁面的那個button或輸入的內容,期望那個元素是什么展示即可,降低了測試人員的代碼門檻,app頁面發生變化時,case維護成本較原來的通篇代碼修改有所降低。
花椒測試平臺整個框架
說了這么多,先來看看花椒測試平臺的整個框架:
該框架主要由三大部分組成,今天主要介紹接口部分的一體化(接口測試+壓力測試):
Web平臺
Web平臺是花椒測試平臺的核心部分,主要是給測試開發人員提供可視化的界面操作,并封裝為參數信息,調用后端的接口服務處理,展示處理結果給用戶。后端采用Springboot + Mybatis框架,前端頁面用jsp開發,后續UI自動化和部分工具的前端頁面也有用vue框架開發,權限管理用的shiro,做好詳細的權限管理,因為如果操作線上case,很有可能會對線上真實用戶造成影響,所以線上case的權限只對部分人員開放,另外比如壓測的功能,也需要做好權限管理,同時后端會記錄每個用戶的操作行為,便于追查。測試平臺模塊主要包含以下幾個:
Case管理
Case管理部分,主要是管理包括接口case,場景case,bvtcase等的增加,修改,和在線執行
接口Case
case增加,刪除,更新,另存為新用例,查找
case結構信息如下:
cases` (
運行環境:測試環境,預發布,線上
模塊:根據業務劃分的模塊
優先級:重要級別
Guid:特殊校驗方式
參數格式:content-type和業務的結合,特殊的業務有特殊定義
用例名稱,用例說明
url:接口url
Token,請求頭信息:請求頭信息里的,Token標識用戶
用例變量:抽取出來的變量,方便更改
請求參數:json結構體key-value的方式存儲請求信息,后端請求的時候按參數個數組裝
期望返回驗證:對結果的校驗,目前有等于,包含,自定義方法上線文驗證等
)
??以用戶更新測試用例為例來看一下整個交互流程:
??用戶瀏覽器一個case,網頁請求后端服務器,Shiro判斷登陸狀態跳轉頁面到第三方登陸,輸入用戶名密碼后調第三方登陸服務,用戶錯誤返回登陸失敗,用戶正確向數據庫查詢用戶角色和權限,返回展示case頁面及有權限的menu,用戶修改case信息,編輯后點擊保存,網頁向服務器請求接口,服務器判斷用戶是否有訪問權限,有權限則保存case更新到數據庫,返回頁面展示保存成功,沒有權限則返回頁面展示“保存失敗,沒有權限操作”
case測試執行
前端獲取頁面的case信息,URL,請求method,加解方式,參數,期望驗證,以form的形式請求后端js_case_execute接口執行測試用例,服務器內部解析請求內容,調用case處理中心模塊CaseRunner組裝請求,向測試服務器發起請求,根據預設的斷言,判斷case的運行接結果,并將結果和服務器的返回組裝成json格式返回給頁面展示,頁面的json展示用了開源的JSONFormatter.js (https://webscripts.softpedia.com/script/Development-Scripts-js/HTML-Tools/JSONFormatter-js-76391.html),能夠根據各個層級展開和疊起,方便測試人員查看數據返回。js_case_excute實行如下:
????@RequestMapping(value?=?"/js_case_execute",?method?=?RequestMethod.POST)
????public?Response?js_case_execute(Case?hjcase,?HttpServletRequest?request)?{
????????RequestUtil.preResetField(request,?hjcase);
????????try?{
????????????List?resultList?=?new?ArrayList();
????????????CaseResult?hjresult?=?new?CaseResult(hjcase.getId(),?hjcase.getCasename(),?-1,?"");
????????????executeCase(hjcase,?hjresult);
????????????resultList.add(hjresult);//?把該case加入我的常用case列表,方便使用
????????????RedisService.addToMyFavCase(SecurityUtils.getSubject().getSession().getAttribute(Const.SESSION_USER),?hjcase.getId()?+?"_"?+?hjcase.getCasename());return?new?Response(resultList);
????????}?catch?(ParamFormatException?e)?{//e.printStackTrace();return?new?Response(1,?e.getMessage());
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();return?new?Response(1,?"Exception---"?+?e.getMessage());
????????}
????}
case批量運行
由于測試過程中經常會有制造批量數據,小并發運行的需求,并發支持對請求變量值設置數組運行,多線程隨機或順序取數組里的用戶執行case,統計case耗時和平均響應時間,頁面設置如下:
批量實現:
??@ResponseBody??@RequestMapping(value?=?"case/batchExecCase")
??public?Response?batchExecCase(Case?hjcasesrc,?HttpServletRequest?request)?{
??????RequestUtil.preResetField(request,?hjcasesrc);
??????if?(hjcasesrc.getCasetype()?==?2)?{
??????????//?suite?case?只支持以數據庫的為準
??????????try?{
??????????????List?subCases?=?caseService.findByIds(hjcasesrc.getCaseids());
??????????????hjcasesrc.setSubCases(subCases);
??????????}?catch?(Exception?e)?{
??????????????e.printStackTrace();
??????????}
??????}//?把需要批量運行是替換的參數解析,需多線程訪問
??????Response?response?=?new?Response();?//?response?傳遞為了返回運行時數據,?所有線程都共享該response,且可以修改其值,?不使用靜態對象是因為多個并發請求會相互影響try?{
??????????List?keyinfos?=?hjcasesrc.getBatchKeyInfos();
??????????httpUtils?utils?=?new?httpUtils();//?提前取用戶登陸信息,獲取出來,?都放入sampleList中,并且設置sampleType=2for?(BatchKeyInfo?keyinfo?:?keyinfos)?{if?(!keyinfo.isToken())?{continue;
??????????????}
??????????????...//省略獲取用戶信息break;
??????????}
??????????response.put(Response.TOTAL,?totalBatch);
??????????List?threadPool?=?new?ArrayList();for?(int?i?=?0;?i???????????????httpUtils?httputils?=?new?httpUtils();
??????????????CaseRunner?runner?=?new?CaseRunner(hjcasesrc,?keyinfos,?httputils,?response);
??????????????runner.setRunTime(totalBatch);
??????????????Thread?runnerThread?=?new?Thread(runner);
??????????????threadPool.add(runnerThread);
??????????}???????long?starttime?=?System.currentTimeMillis();for?(Thread?worktask?:?threadPool)?{
??????????????worktask.start();
??????????????worktask.join();
??????????}long?endtime?=?System.currentTimeMillis();float?avgTPS?=?(float)?totalBatch?/?((endtime?-?starttime)?/?1000.0f);
??????????response.put("Comsume",?endtime?-?starttime);
??????????response.put("avgTPS",?String.valueOf(avgTPS));
??????}?catch?(Exception?e)?{
??????????e.printStackTrace();
??????}return?new?Response(response.getResultJSON());
??}
場景case
場景case來源于用戶的一系列有聯系的操作行為,比如用戶A想要和主播B連麥,A先發起連麥,B主播同意,A用戶同意,然后用戶A和主播B連麥成功,這里面就有3個接口,一個是發起的apply接口,同意的accept接口,和開始連接的connect接口,所以組成這個場景的子case有三個,case1用戶A發起apply,成功后返回申請的id傳遞給case2/case3, case2主播accept連麥, 請求的用戶信息是主播B, case3用戶B開始connect連麥。執行的整個過程是,先抽取變量,執行case1,處理斷言信息,賦值返回的申請id,然后執行case2,case2的傳參申請id用case1返回的id同意申請,case3用case1的申請id開始連麥,整個過程的順序必須是case1->case2->case3。場景 case存儲時,抽離出每個case的用戶信息,輸入,期望判斷信息,如“0”:values,組成一個大的jsonobject,case運行時,解析結構體,順序執行,case的主數據庫結果體信息如下:
BVTCase集
BVTCase為各模塊接口case集管理中心,case集可以共享請求服務器地址,用戶等信息,case集內可以定義case的執行優先級,執行整個case集,查看執行結果,對外給發布系統提供查詢,執行測試集的接口并返回結果給發布系統判斷是否允許發布。另外也增加了crontab任務定期執行。
新建測試Suite,編輯測試Suite,編輯測試case順序,執行測試Suite,批量執行測試Suite
對外代碼發布系統獲取測試Suite列表,指定測試Suite信息,調用測試Suite執行
inter/getSuiteLists獲取測試集列表,可指定模塊,如passport,live等
inter/getSuiteInfo獲取指定id的suite信息,全部變量及各子case信息
inter/execSuiteList執行測試集,并返回測試集執行結果,成功失敗,測試集的詳細結果的訪問方式
結果集,為測試suite執行的結果列表頁面,記錄執行結果,耗時已經執行人的信息:
結果集名稱,總條數,成功條數,失敗條數,狀態(成功,失敗),執行人
工具管理
平臺工具管理中心,主要包含兩種類型的工具,一種是jar包等上傳可執行文件的工具,一種是在線使用工具:
可執行文件工具
平臺支持添加腳本,上傳jar包,指定傳入的參數等,保存腳本信息,支持編輯更新,測試執行在線使用的工具
該類工具如網頁版的redis查詢工具,byte string轉換,數據清理等各種小工具,可以根據業務測試中的各種需求開發各種能提升效率的小工具,如下面這個byte string轉換小工具,功能很簡單,但解決了手工測試無法看到內容的困擾,提升了定位問題的效率
壓力測試管理
壓測場景
支持新建,更新壓測場景,壓測場景綁定已經建好的接口測試用例,修改用例變量值如用戶id來實現多用戶壓測場景,壓測場景包含的信息如下:
壓測場景{
模塊:選擇壓測場景屬于的業務模塊
用例id:選擇壓測的case
壓測場景:壓測的場景的名字
場景說明:該壓測的信息說明,如多少個用戶,多少并發
壓測服務部署機器:部署壓測服務的機器IP
啟動線程個數:并發線程個數
運行次數:執行多少次case
發送間隔:每個線程每個請求處理完后的休息間隔(可為0)
用例變量:從選擇的用例id里帶過來的用例變量,便于壓測過程中修改方便
壓測參數:對用例變量進行取集合值,或從指定數值開始的多少個數,常用于多用戶的場景壓測
}
壓測執行
點擊啟動壓測任務
壓測結果
點擊結束任務時,當次壓測的數據匯總回寫到結果數據表,統計請求TPS(reqTPS),響應時間(respTime),響應TPS(respTPS)的最大最小值和平均值,以及總請求個數,以及失敗的請求個數。
壓測服務
壓測服務是執行壓力測試的中心服務,可以部署在任意可執行壓測任務的服務器(有java環境即可),主要邏輯是監聽從web,或者PC壓測Client傳過來的壓測指令,根據執行獲取壓測信息,起線程進行壓力測試,每秒統計一次壓測數據,并將數據同步到數據庫,供web平臺展示查看實時壓測結果并進行壓測調整。
主要包含以下幾個主要模塊:
監聽服務
監聽務是指啟動一個socket server來監聽指定端口,收到指令,為了保證安全性,先判斷指令發送IP是否在白名單內,如不在,拒絕服務;解析命令內容,命令內容以TasK*開頭,則代表從測試平臺來的命令,執行相應操作,如啟動任務,執行壓測任務(CaseRunner分支),更新任務信息,結果任務等;如果命令內容直接以Start,任務名稱等開頭,則走自定義壓測執行壓測任務(WorkTask分支),自定義部分適合復雜場景和統計需求的壓測。
...//以收到啟動命令為例if(cmd.equals("TaskStart")){?//?啟動線程,初始化變量???????????????????????????????????
????int?content?=?Integer.parseInt(params[1]);?????????????????????????????????????????????//?非結束狀態,說明?可能有些初始化或銷毀操作是需要進行的,?必須&&?非下面兩種狀態時處理?????????????
????if(CommonTaskData.getSTATE()?==?CommonTaskData.RUNNING?||?CommonTaskData.getSTATE()?==?CommonTaskData.PAUSE)???//?從?start?之后?還是start--????????????????????????
????{
????????if(CommonTaskData.getId()?==?content)?{
????????????//?如果還是同一個task,?則只需重新更新一下task即可??
????????????CaseHelper?casehelper?=?CaseHelper.getInstance();?????????????????????????????????????????StressTaskHistory?taskhistory?=?casehelper.getTaskHistory(content);???????????????????????CommonTaskData.setTask(taskhistory.parseStressTask());???????????????????????????????????System.out.println("從暫停狀態中恢復~~");???????????????????????????????????????????????????for(CaseRunner?runner?:?caseRunners){??????????????????????????????????????????????????????????????runner.setState(CommonTaskData.RUNNING);???????????????????????????
????????????}?
????????????CommonTaskData.setSTATE(CommonTaskData.RUNNING);???????????????????????????????????????????????????????????????????continue;??????????????????????????????
????????}?else{?
????????????System.out.println("不同TaskId?Start?----先清理之前線程");???????????????????????????????????for(CaseRunner?runner?:?caseRunners){
????????????????runner.setState(CommonTaskData.STOP);?????????????????????????????????
????????????}
????????????for(Thread?worktask?:?threadPool){//?等待3s的銷毀時間?銷毀原來的線程池
????????????????try?{
????????????????????worktask.join();????????????????????????????????????
????????????????}?catch?(InterruptedException?e)?{
????????????????????e.printStackTrace();????????????????????????????????????
????????????????}?????????????????????????????????????????????????????????????????
????????????}???????????????????????????????????????????????????????????????
????????}????????????????????????
????}
????Statistics.startSampling();?//啟動壓測統計服務
????...//準備壓測執行的數據,讀取case和task信息???
????//設置運行狀態,啟動線程
????CommonTaskData.setSTATE(CommonTaskData.RUNNING);?????????????????????????
????for(int?i?=0;?i?????????CaseRunner?runner?=?new?CaseRunner();???????????????????????????
????????runner.setState(CommonTaskData.RUNNING);???????????????????????????
????????Thread?worktask?=?new?Thread(runner);???????????????????????????
????????threadPool.add(worktask);???????????????????????????
????????caseRunners.add(runner);???????????????????????????
????????worktask.start();????????????????????????}?????????????????????????????????????????????}
????...
壓測任務處理
根據測試平臺或PC client發過來壓測任務,CaseRunner執行相應的case,并將請求的結果,如成功與否,請求的響應時間等發送給Statistic統計服務進行打點統計,目前CaseRunner執行方式的壓測適用與web的http同步請求,而自定義壓測方式的worktask則既可以定義同步的等待響應后發送下一個請求的方式;也可定義直接往服務器扔請求,異步接收線程處理響應結果及給Statistic統計服務發送打點數據。下面一CaseRunner同步執行的方式為例:
@Overridepublic?void?run()?{?????????
while(true)
{????????????
????...停止,暫停等狀態,中斷執行
?????casedata.copyFrom(CommonTaskData.getBasecase());?
?????casedata.appendGlobalVar(varMap);
?????CaseResult??caseresult?=?new?CaseResult();
?????String?actionName?=?"Task"?+?CommonTaskData.getTask().getId();
?????try?{
?????????Statistics.OnRequestSend(actionName);
?????????long?pre?=?System.currentTimeMillis();
?????????utils.runCase(casedata,?caseresult);
?????????long?after?=?System.currentTimeMillis();
?????????//根據case執行成功失敗,打點
?????????if?(caseresult.getStatus()?==?1)?{
?????????????Statistics.OnResponseRecv(actionName);
?????????????Statistics.onResponseTimeRecv(actionName,?after?-?pre);
?????????}
?????????else{?????????????????????
?????????????Statistics.onFailedResp(actionName);
?????????????try{
?????????????????if(casedata.getCasetype()?==?1){
?????????????????????...//根據case里設置的斷言,統計特殊需求的失敗,總個數和失敗請求的響應時間
?????????????????}
?????????????}
?????????????catch(Exception?e)
?????????????{????
????????????????System.out.println("CaseRunner(114)?-?Exception-"?+?e.getMessage());?
?????????????}
?????????????Logger.SysOutput("Fail:"?+?caseresult.getResult().toString());
?????????}????
?????}?catch?(Exception?e)?{
?????????e.printStackTrace();
?????????Logger.SysOutput("CaseRunner(123)?-?Exception:"?+?e.getMessage());
?????}
?????//?測試場景如果設置的發送間隔,則sleep
?????if(CommonTaskData.getSleeptime()?>?0){
????????????if(CommonTaskData.getSleepRan()?==?1){
?????????????????Tools.sleep(RamNum.GetRamInt(CommonTaskData.getSleeptime()));????????????
????????????}else{
?????????????????Tools.sleep(CommonTaskData.getSleeptime());
????????????}????????????????
?????}
}
}
Statistic壓測結果統計
統計每秒的請求數,響應數,響應時間,失敗數等,如果是平臺的壓測請求,將壓測數據根據需求記入數據庫,供web平臺展示用,具體實現如下
@Overridepublic?void?run()?{????long?lastSampleTime;
????while(!stopSample){
????lastSampleTime?=?System.currentTimeMillis();
????try{
????????Thread.sleep(samplePeriod);
????????Object[]?actionNameSet?=?actions.keySet().toArray();
????????for(Object?key?:?actionNameSet){
????????????Action?action?=?actions.get(key.toString());
????????????if?(!key.toString().startsWith("Task"))?{
????????????????action.Sample(lastSampleTime);//統計請求信息,并打印
????????????????action.SampleResponseTime(lastSampleTime);//統計響應時間信息,并打印
????????????}?else?{
????????????????action.SampleRedis(lastSampleTime);//統計請求信息,響應,打印并存庫
????????????}
????????}
????}catch(InterruptedException?e){
????????System.out.println("Sample?thread?stop?for?interrupted?exception.");
????????break;
????}
}
}
后續計劃
目前測試平臺只集成了自動化測試的基本功能,在持續集成上的應用還需要豐富起來,另外作為一個質量管理平臺,對提測->測試 -> 測試bug記錄->測試結果->上線的整個過程并沒有完整的整合起來,也是我們后續需要完善的地方。
- To Be Continued?-
我建立的知識星球,提升技術認知,助力技術成長!歡迎掃碼加入:
總結
以上是生活随笔為你收集整理的接口入参形式_花椒测试平台 接口篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: led大屏按实际尺寸设计画面_“差评”不
- 下一篇: 小米Civi 2情人节特别版!Hello