自動化接口測試實踐經驗
作者:faithchen,騰訊 PCG 測試開發工程師
一、背景
自動化測試對於我們提升研發效能、CI/CD(持續集成 / 持續交付) 是不可或缺的部分。在後臺自動化測試中,接口測試尤爲重要,它能夠保證被測後臺服務的質量,以及接口邏輯的正確性等,幫助我們快速測試功能、提高測試覆蓋率、把控質量風險等。
1.1 後臺接口測試
接口測試是功能測試的一種,是測試系統組件間接口的一種測試,重點在於檢驗對於服務接口的數據交換的正確性,一般全部依賴真實鏈路,測試時需要啓動被測服務。如下圖是某個 Server A 的接口測試:
然而,寫過接口測試的同學可能都會被複雜的數據構造以及繁雜的斷言所困擾,可能需要耗費大半天才能寫完一個接口測試用例,浪費了許多寶貴的時間!基於以上考慮,爲了提高編寫接口測試用例的效率,我們希望能夠自動化地協助開發或測試人員完成這些耗時耗力的事情,爲此而產生的想法是通過流量的錄製,再通過錄制的流量自動化生成接口測試用例。基於上述想法,我們提供了從錄製流量到生成接口測試用例完整鏈路的工具,輔助開發同學快速完成編寫接口測試用例。簡單來說,只需要以下三個步驟便可以接入:
接下來,我們通過 **“流量錄製 -> 生成用例” 的流程來進行闡述我們的實現方法和接入方式。我們會說明通用的平臺如 stke、sumeru 服務的接入流程,由於 123 平臺對 goreplay 等有較好的支持,除了通用流程外會以 123 平臺爲例進行說明。最後會說明流量頻次篩選方案 ** 幫助大家理解我們的流程。
二、流量錄製
2.1 流量錄製簡介
2.1.1 什麼是流量錄製
我們聽得比較多的是 “錄製與回放”,但目前只需要用到錄製功能,後續可能會把回放功能也加上。顧名思義,流量錄製就是指將我們期望的接口數據的包括 response、request、協議等等存儲起來的操作,可以是正式環境或者是測試環境的數據,開啓了錄製功能後,只要對應環境的服務有流量,便可以將其捕獲存儲起來,實現此功能的方式有多種。
通過對多個方案的對比後,我們決定採用 goreplay 的方式,其開源代碼是 goreplay ,基於 goreplay 1.2.0 版本改造後已經支持 trpc, http, gofree, wup, videopacket, 後面會陸陸續續支持其他協議,採用 goreplay 的主要優勢是它可以分析和記錄服務的流量但不會影響服務,並且接入流程相對簡單。
goreplay 方案其最大好處是與業務代碼解耦,不需要入侵代碼。
在傳輸層的 goreplay 錄製方式爲:
2.1.2 爲什麼要進行流量錄製
接口測試是在真實運行的服務中測試,若想自動化生成用例,理想的情況下,便是要自動化生成真實數據的接口測試用例,那麼首先需要的就是真實的接口數據,數據從何而來呢?自然而然的,我們便會想到到線上去錄製(無論是測試環境或者正式環境的)。
下面爲「通用流程」講述如何爲服務接入 goreplay 流量錄製流程。
2.2 「通用流程」服務流量錄製
2.2.1 「通用流程」上傳 pb 文件至協議中臺用於解析二進制流量
首先我們需要一個能夠管理協議的系統,它能夠對協議文件(如 pb 文件等)進行管理,這樣當協議有更新時,依然能夠對新的協議生成的流量進行解析。
能夠將 goreplay 錄製的二進制數據進行解析:
只需要將依賴的 proto 文件進行打包(注意依賴多個 proto 文件時保持相對目錄正確)並上傳到協議中臺即可,並且生成對應此版本 pb 的版本號,用於我們後續生成 goreplay 命令。
2.2.2 「通用流程」生成並執行 goReplay 命令
在上述協議中臺獲取了版本號之後,我們已知後臺服務的 ip 和端口,已經最新的協議版本。將這些填入我們的 goreplay 命令中,如下圖所示:
將上述命令在對應的容器中執行。
部分參數說明:
--input-raw-logreplay// 這個其實是rawInput插件的參數, 開啓這個參數後, 必須ip和port都要填
--output-logreplay-cache-size 200// LogReplayOutPut插件 需要的緩存大小, 可以不設置, 有默認值
--output-logreplay-track-response// 跟--input-raw-track-response含義一樣
--input-raw-protocol // 必填需要解析的協議
--output-logreplay-protocol-service-name "app.server" // 協議文件對的服務名
--output-logreplay-commitid "1.0.1" // 必填,如果是http協議, 可以自定義
--output-logreplay-qps-limit 100// 限制錄製的qps, 非必填, 有默認值
--output-logreplay-env formal // 選填,默認formal,需要註冊到logreplay測試環境可填test
在容器中執行ps -ef|grep goreplay
看到如圖進程便表示成功了:
2.2.3「通用流程」查看錄製流量
當服務在對應環境有流量的話,很快我們就可以查看到通過 goreplay 錄製到並解析成功的流量了。
裏面的 request 和 respond 等數據都一目瞭然(此處是 demo 所以數據很少,真實環境中,可能有非常多的參數及數據),根據這些錄製的數據,我們下來就可以自動生成接口測試用例了。
三、生成用例
當錄製好流量後,我們會有一個篩選機制來過濾流量,不過這個操作對於用戶是無感知的。對於使用方來說,接下來就能夠自動化生成流量了。
3.1 px-cmdline 工具簡介
我們提供了 px-cmdline 工具,這是一個命令行工具,它可以將 goreplay 錄製的流量,通過 proto 文件,自動獲取相關依賴後生成符合代碼規範的接口測試文件。
3.2 px-cmdline 使用
使用方式也很簡單,命令行格式爲:
px-cmdline generate -p <proto gomod> [-f] [--env test]
常用參數介紹:
-
-p 指定 proto 依賴路徑,從 go.mod 中拷貝
-
-f 是否強制更新,開啓後,會替換掉即將生成的同名接口測試文件
-
--env 指定拉取流量的環境變量,默認 test 環境
-
--dest 指定生成的目錄,默認 tests 文件夾
-
-j 指定是否切換 json 文件模式。默認使用 json 文件獨立模式;開啓後,用例寫入到 *_test.go 裏
示例:
px-cmdline generate -p git.code.oa.com/xxxxprotocol/hello/world
運行後,如果未發生異常,會在當前目錄下生成 tests 子目錄,根據每個 RPC 接口生成獨立的__test.go 文件,以及一個唯一的 suite_bvt_base_test.go 用於啓動接口測試。testdata 目錄存放 json 格式的用例數據。如圖:
當服務有多個運行節點的時候,還支持選擇運行節點,以便用於本地調試接口用例時請求該目標。建議優先選擇 test 環境或者開發者的特性環境
[Info] 請選擇本地測試目標服務:可只選擇環境,或指定節點
[Info] (1) 測試環境 test --------
[Info] (└ 11 ) 9.2.3.4:16916, Development, 權重100, 健康
[Info] (2) 特性環境 sdfdfe --------
[Info] (└ 21 ) 11.1.2.3:11389, Development, 權重100, 健康
[Info] (3) 特性環境 dfadfb --------
[Info] (└ 31 ) 9.3.4.5:11042, Development, 權重100, 健康
[Info] (4) 特性環境 c9d193e8 --------
[Info] (└ 41 ) 11.3.4.5:11222, Development, 權重100, 健康
爲了符合代碼規範,用例數據目前以 json 數據的形式進行存儲,展示其中一條數據如下:
{
"request": "{\"pp\":[\"1dfa\"]}",
"response": "{\"sdf\":{\"TPDKH\":{\"basic\":{},\"cosume\":{},\"data\":{\"type\":\"NotSettle\",\"pll\":[733],\"tpl\":\"UG\"}",
"trace_id": "394729374872934"
},
如此一來就成功生成了接口測試用例了,當我們本地調試 OK 後,就可以將其 mr 進代碼主幹,在日常流水線運行時都能對接口進行自動化測試。
當然了,如果有同學喜歡用更直觀的 IDE 工具,我們也提供了 IDE 插件供大家使用。
3.3 px-cmdline 工具(IDE 版) Jetbrains 插件使用
如果用戶希望通過 IDE 插件,可以通過如下操作
第一步:我們有相關的插件供安裝
彈出窗裏面選擇剛纔下載的 ZIP 包,然後確定;
第二步:安裝完成後重啓 IDE,啓用插件通過插件簡單右鍵選擇來生成接口測試文件可以達到與命令行工具同樣的效果:
img
然後便可以順利生成接口和用例在特定的文件夾中,用於接口測試執行。
四、流量頻次篩選策略
本章節補充說明,當我們數據量較大的時候,如何進行篩選與分析,保留下相對有價值的流量用於生成接口測試用例的。
4.1 流量篩選背景
本章節內容講述我們的流量篩選策略,這部分內容對於使用用戶是無感知的,但是有助於對我們工具的完整鏈路有更好的理解。
當我們爲服務接入 goreplay 後,在服務上有成千上萬的流量錄製進來,有時候甚至更多,那麼怎麼知道哪些流量是重複的,哪些流量值得記錄下來用於生成用例呢?
由於正式線上環境流量較大,可能存在很多流量數據的重複率和相似度較高的情況,對此,我們不會簡單的將所有流量都直接存儲到數據後用於後續生成接口測試(畢竟我們也不可能用成千上萬個接口用例來測試一條數據),而是會通過一定的策略進行頻次篩選,符合我們相似度區分要求的流量我們纔會存儲到我們的數據庫中。
這樣做的好處有:
-
防止某些服務流量過大,存儲數據過大。
-
剔除重複流量,對於相似度高的流量不重複存儲,同時保證了接口測試的數據多樣化。
4.2 相似度對比簡述
4.2.1 相似度比較總體流程
如下圖,例子中有兩個流量的 response,我們是如何對 response 或者 request 的數據進行相似度計算的呢,大致流程爲:
-
取其 body 部分,捨棄 header
-
計算一級 key 相似度,一級 key 的相似度我們較嚴格,一般情況下,如果一級 key 不一樣那麼則可以認爲這兩個 body 之間的差異是較大的,如下圖左側 response 的一級 key 有
Msg
、ProcId
、TaskOutput
,右側 response 的一級 key 有Msg
、ProcId
、Code
,顯然,我們會認爲這兩個相似度是較低的,應該是差異較大的流量。 -
假如一級 key 完全一樣的話,顯然要進一步遞歸比較,但是層級越高我們會設置影響因子越小,對此完成相似度的遞歸計算。
4.2.2 字符串相似度
一般計算到二級 key 以後,我們便要開始關心字符串的相似度了,此處我們使用的算法是 Levenshtein 距離 ,定義如下:
簡單說來,就是計算一個字符串需要經過多少次編輯才能變成另一個字符串,結合它們的字符長度和編輯次數,我們便可以計算兩者之間的相似度。
例如,將 “kitten” 一字轉成 “sitting” 的萊文斯坦距離爲 3:
-
k itten → s itten (k→s)
-
sitt e n → sitt i n (e→i)
-
sittin → sittin g (插入 g)
當獲得字符串相似度之後,進而可以計算出 json 的相似度即 response 和 request 的相似度,再結合多級 key 的影響因子策略進而計算出兩條流量的相似度。
4.3 篩選策略
獲得相似度之後,我們還會通過多層策略來篩選。
-
設置 response 和 request 的比重,因爲通常 response 更好地反應接口的差異,設置比重可以更好的衡量流量間的相似度,利於後續篩選。
-
設置多層動態閾值,隨着數據量的增加,動態調節能夠存入的相似度閾值,以便更好地控制記錄的流量數目,保證記錄下來的流量數在後期是收斂的,不會無限增加。
-
記錄流量重複次數,可以用於後續生成用例,我們認爲重複更多次數的流量其重要性越大。
通過多重策略,來保證我們能夠篩選出 “優質” 的流量用於後續接口測試。
五、總結及其他
目前本方案已經爲多個服務(包括微視、企鵝號等)生成多條接口測試用例,已經超過 1000 條合入到服務中在日常 mr 中進行接口測試。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/WrfaCt39Jb4vViKB2-qynw