JMeter+GoCD實(shí)現(xiàn)API自動化測試

????這篇記錄一下從選型到初步實(shí)現(xiàn)方案成形踩過的坑。。。

前情提要&技術(shù)選型

????團(tuán)隊(duì)需要接口自動化測試用以檢查:

? ? ? ?(1)接口返回的數(shù)據(jù)是否與預(yù)期結(jié)果一致。

? ? ? ?(2)檢查接口的容錯性,假如傳遞數(shù)據(jù)的類型錯誤時是否可以處理。

? ? ? ?(3)接口參數(shù)的邊界值。例如,傳遞的參數(shù)足夠大或?yàn)樨?fù)數(shù)時,接口是否可以正常處理。

? ?在技術(shù)選型方面尋找了下面4種接口自動化的測試工具,對其優(yōu)缺點(diǎn)進(jìn)行了分析討論:

? ??1. postman newman

????特點(diǎn):可以快速構(gòu)建請求、保存以供以后使用,并分析API發(fā)送的響應(yīng) -> 最簡單,最容易上手

????不方便版本控制,可擴(kuò)展性較差,case校驗(yàn)方式較少

????2. JMeter

????特點(diǎn):提供了圖形化界面,上手容易,插件豐富,除了api測試還可以做壓力測試,可以使用非gui模式運(yùn)行測試腳本

????測試腳本維護(hù)方便,可以將測試腳本復(fù)制,并且可以將某一部分單獨(dú)保存

????使用參數(shù)化以及Jmeter提供的函數(shù)功能,可以快速完成測試數(shù)據(jù)的添加修改

????Jmeter腳本的維護(hù)需要保存為本地文件,

????測試文件為類xml格式,易讀性較差,不方便做版本控制

????3. RobotFramework

????Robotframework的httplibrary庫

????支持關(guān)鍵字驅(qū)動,提供圖形化界面

????編寫用例簡單方便,可以用txt,tsv或html等格式編寫用例

????測試報告和日志為html格式,易于閱讀

????界面反應(yīng)速度慢,經(jīng)??ㄋ?/p>

????導(dǎo)入測試庫可能會有異常

????沒有非圖形化操作方式,無法版本控制

????4. Python+requests / Java+httpclient

????簡潔優(yōu)雅,功能強(qiáng)大,方便版本控制,可根據(jù)team需求自定義測試結(jié)構(gòu)

????對于Dev比較友好,沒有可視化的報告(可以考慮加入如log4j這樣的日志工具

? ? 一開始我是推薦第4個使用httpclient or requests庫這樣的來寫自動化腳本,但是考慮到對測試人員的友好,同時未來的性能測試/壓力測試,最后選擇了JMeter。

實(shí)踐過程

????測試框架的整體思路是使用JMeter編寫http請求測試腳本,在QA環(huán)境中模擬用戶進(jìn)行真實(shí)的http請求,使用斷言判斷返回的狀態(tài)碼和返回信息。并將JMeter集成進(jìn)GoCD的持續(xù)集成平臺,打一個docker運(yùn)行在云主機(jī)中,對自動化測試使用單獨(dú)的pipeline,當(dāng)代碼被部署到環(huán)境時自動run自動化測試的pipeline。

????夢想很豐滿,顯示很骨感,在實(shí)踐過程中發(fā)現(xiàn)了若干問題,具體問題如下:

1. json數(shù)據(jù)如何動態(tài)獲取

????在調(diào)用api之前都需要發(fā)送一個申請access token的http請求,再使用access token去調(diào)用其他的api。返回的數(shù)據(jù)樣式如下??

{ "access_token": "xxx", "type1": "this is type1", "type2": 1, "type3": "this is type3"}

????而且這個access token還是一小時一刷新的,只好動態(tài)獲取其值,為了提取access_token里的值,使用了正則表達(dá)提取理器(Regular Expression Extractor)

????Name of created variable是提取出變量的名稱,Regular Expression是待匹配正則表達(dá)式,這里我用的是"access_token":"(.+?)",需要注意的一點(diǎn)是,當(dāng)時我拿著postman生成的結(jié)果去做正則匹配,匹配match之后拿到JMeter里,但是在JMeter上匹配出來的結(jié)果始終match不上,調(diào)了半天發(fā)現(xiàn)Postman里的返回Json數(shù)據(jù)美化了,有了多余的空格,而Jmeter里拿回來的數(shù)據(jù),所以始終match不上。Template:用$$引用起來,如果在正則表達(dá)式中有多個正則表達(dá)式,則可以是$2$$3$等等,表示解析到的第幾個值給title。如:$1$表示解析到的第1個值。Match No. 匹配的第n個值,如果選0就代表隨機(jī)選,因?yàn)檫@里只有一個access token,所以給0也無所謂啦~~~,Default Value缺省值,如果找不到就給一個默認(rèn)的值。

????驗(yàn)證一下提取的結(jié)果,為了觀察變量的值,可以添加一個Debug Sampler,驗(yàn)證一下發(fā)現(xiàn)可以成功提取,歐耶~~

????但是另一個問題接踵而至,為了區(qū)分不同的http請求,這里使用了多個Thread來run測試腳本,當(dāng)前提取出來的token只能用在當(dāng)前Thread里,要么全部http請求寫在一個Thread里,要么就分開使用全局變量。前者很明顯是不make sense的,如果想只運(yùn)行部分測試腳本就變得異常困難,那么就要如何將提取出的變量變?yōu)槿肿兞俊?/p>

????找了半天,找到了BeanShell Sampler,采用通過添加shell腳本的方式來將本線程的變量變?yōu)槿肿兞?/p>

????如上圖,它將本線程內(nèi)的token變量,加上了全局引用,引用名為newtoken,在實(shí)際使用的時候就可以用${__property(newtoken)}來全局引用token。啊對還有一點(diǎn),當(dāng)這個測試腳本run一遍之后,變量值就會被默認(rèn)存儲,這個時候再去run其他獨(dú)立的測試線程,也可以使用剛剛得到的參數(shù),而不用每次都從頭到尾都run一遍了。

2. 加密信息如何處理

????HTTP請求中的header有一些賬號密碼是私密信息,存入團(tuán)隊(duì)的git倉庫中可能會造成密碼泄露,如果貿(mào)然的將未加密的信息上傳到代碼倉庫里恐怕我就見不到明天的太陽了,so分兩步走,因?yàn)榇郎y試的jmx文件有很多,首先將所有secret信息統(tǒng)一存入一個文件,在測試文件里直接對其引用就好,再單獨(dú)對這個secret信息進(jìn)行加密即可。JMeter中的Config中有一個CSV Data Set Config,支持使用csv(據(jù)說txt的文本格式也行,我沒試過)格式的數(shù)據(jù)導(dǎo)入,方便批量測試數(shù)據(jù)的導(dǎo)入,當(dāng)然這里我沒用上哈,我只是配了一行數(shù)據(jù)即待加密的信息,配置如下:

????這樣就可以在JMeter里直接調(diào)用${_token}和${_key}這兩個變量啦。

????解決了加密信息統(tǒng)一存儲的問題,接下來就要對信息進(jìn)行加密了,將加密后的信息存入代碼庫中,run的時候?qū)⑵浣饷芫托?,這里使用了git-crypt對其進(jìn)行加密,在配置pipeline的時候把解密的命令配進(jìn)去就妥妥的了,具體過程不表,因?yàn)槭荄ev幫忙寫的=。=

3. 錯誤的HTTP狀態(tài)碼如何讓測試通過

????對于一些測試非法情況的場景,我們期望其返回的HTTP Code就是404,但是不期望它是502,這里加入了斷言,判斷其返回的狀態(tài)碼是否是404,但是JMeter依然判定我測試失敗,搞了半天才發(fā)現(xiàn)需要在斷言里把Ignore Status給勾上,如下圖所示,如果遇到了400,斷言通過,同時忽略這個錯誤狀態(tài),測試就pass啦~

4. 如何集成進(jìn)GoCD

????至此JMeter的配置已經(jīng)完全結(jié)束,現(xiàn)在已經(jīng)可以全自動的實(shí)時獲取token,并使用token發(fā)送http請求。同時對敏感信息進(jìn)行了加密,保證不被泄露。下面最坑的地方來了,因?yàn)閳F(tuán)隊(duì)使用的持續(xù)集成(CI)工具是GoCD,如何將其集成進(jìn)GoCD便成為了我最頭疼的問題,GoCD是ThoughtWorks開發(fā)的一款持續(xù)集成工具,但是生態(tài)不如同為CI工具的Jenkins那么友好,Jenkins直接提供了JMeter配置方式。針對如何集成進(jìn)GoCD我先后想了兩個方案,到最后終于填坑,敘述一下心路歷程。

4.1 方案1:寫一個shell腳本

????首先第一個考慮到的思路是使用JMeter的無GUI模式,即用命令行的方式運(yùn)行一個測試腳本,JMeter可以使用下面的命令來通過命令行的方式來run一個測試腳本:

jmeter -n -t test2.jmx -l result.jtl

????-n即打開no gui模式,-t指定配置文件,-l指定測試report的名稱/地址。run一遍之后我們可以看到命令行有如下輸出:

????JMeter會提供一個general的report,目前有意義的數(shù)據(jù)只有Error的數(shù)量,如果想看更詳細(xì)的可以打開我們指定的result.jtl

????這其實(shí)也是個csv數(shù)據(jù)啦,觀察到第10列failureMessage如果測試通過則字符串為空,如果不通過字符串不為空比如:Test failed: code expected to match /201/。

????但是當(dāng)我把腳本run在GoCD上的時候,發(fā)現(xiàn)無論有幾個Error都不會導(dǎo)致pipeline的failed,全部passed(如下圖),仰天長嘯天要亡我,尋思了半天想了想只能從0開始造輪子了,因?yàn)镚oCD是根據(jù)程序的返回值來判斷成功或失敗,如果我讓它返回的不是非0不就可以讓pipeline掛掉了嘛=。=

????至此方案1的思路就已經(jīng)初步有了,通過判斷輸出的測試report中每行第10個數(shù)據(jù)項(xiàng)(failureMessage)是否為空來推斷是否測試通過,或者可以通過命令行標(biāo)準(zhǔn)輸出中的Error數(shù)量來判斷,只要Err:后面的數(shù)字不為0即為測試失敗,直接輸出得到的數(shù)值即可,想了想選擇了第一個方案去嘗試,因?yàn)榭紤]到需要在控制臺輸出詳細(xì)的錯誤原因方便調(diào)試。這里嘗試使用shell腳本來完成這個任務(wù)。

????shell腳本的大體思路是顯示輸出一個命令,再獲取輸出的測試report,對于每一行字符串(即run的每個測試腳本)按照逗號分隔,判斷分隔出的第10個字符串是否為空,如果不為空就輸出錯誤信息,最后返回錯誤代碼即可讓pipeline為failed,代碼如下:

????但是這個方案我自己都覺得很不健壯,因?yàn)槲乙坏┰跍y試用例名稱里加了一個逗號,都會導(dǎo)致這個腳本的崩潰。同時需要在主機(jī)里安裝JMeter的客戶端,那就更費(fèi)事了。。。Mac上好歹可以brew安裝,Linux上就要一頓操作猛如虎了,果斷棄坑。

4.2 方案2:使用gradle插件

4.2.1 配置gradle插件

????此路不同自有別路,同事提出了一個新思路,JMeter有Gradle插件,可以直接調(diào)用,比我的方案1不知道高到哪里去了,我就趕緊琢磨了一下,這是JMeter的Gradle插件link,整理了一下發(fā)現(xiàn)真是好用啊。。。(雖然只有40顆星),基本用法就三條

????gradle jmGui -> 通過gradle命令打開一個JMeter窗口客戶端

????gradle jmRun -> 運(yùn)行JMeter腳本????

????gradle jmReport ->生成HTML的測試報告,更易讀

????這樣不但解決了安裝JMeter的問題,也搞定了運(yùn)行腳本的痛,這個插件可以判斷是否有測試失敗的腳本,如果有則pipeline構(gòu)建失敗。

????具體的配置可以去網(wǎng)站自行查找,這里只說一點(diǎn)坑的地方,我在嘗試使用jmReport生成報告的時候死活生成不了,說找不到result文件,后來在GitHub里的答疑板塊參考了德國老哥的gradle配置,同時好像需要從本地JMeter里copy一個jmeter-results-detail-report_21.xsl,再運(yùn)行jmReport就好使了,具體配置如下:

4.2.2 輸出report到控制臺

????終于搞定了Gradle插件,美滋滋的將其上到GoCD的Pipeline上,但是發(fā)現(xiàn)這玩意死活不給錯誤信息,只告訴我錯了,自己去看log,我云主機(jī)咋看log嘛。。。找了半天都沒找到可以用來輸出的參數(shù),甚至想去改他插件了。。。痛定思痛想到了因?yàn)檫@里我指定輸出的test report為xml格式,我可以通過Groovy自帶的XML解析來完成這個,通過解析<failureMessage>判斷是否為空,如果不為空輸出這一個區(qū)域的附加信息,代碼如下:

????至此全部配置完成,GoCD的Pipeline就不表了,正常配就ok,最后的效果圖

JMeter腳本run失敗的情況
讀取測試Report并輸出錯誤原因

????一點(diǎn)拙見,想法還不成熟,歡迎大佬們點(diǎn)評指正~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容