簡易版的接口流量回放工具Parrot


寫在前面

軟件測試在很多時候都是流量回放的模式,這里的“流量回放”的定義比較寬泛,通常包含如下三個步驟:

  • 錄制:定義/獲取執行步驟和預期結果
  • 回放:執行預定步驟,收集實際結果
  • 驗證:對比預期結果和實際結果,判定測試結果

軟件測試的一般定義:按照既定的步驟,運行系統或應用程序,得到實際結果,和預期結果進行比較。

本文主要介紹http接口的流量回放方式,目的是取代常規的接口自動化,暫無法應用於性能測試。

項目開源地址:https://github.com/idle-man/Parrot (代碼比較粗糙,歡迎指教)


步驟一:錄制

前面有提到,錄制主要是定義/獲取執行步驟和預期結果,就接口測試而言,需要拿到的信息有:

  • 被調用的接口及傳參
  • 接口間的調用順序及依賴關系
  • 各接口的預期響應

綜合業界常見的測試方式和已有的流量回放手段,通常有以下幾種錄制方式:

  • 生產環境引流:采用TCPDump、TCPCopy或網關/路由層進行轉發;該方式需要一定的部署權限
  • 離線日志解析:基於標准化的日志解析得到完整信息;該方式對日志規范化有較高的統一的要求
  • 測試工具抓包:如Fiddler、Charles,測試及回歸過程中均可積累;可做標准化解析,數據量級相對較小
  • 接口文檔定義:基於嚴格的標准化接口文檔;該方式條件相對苛刻很多,且接口文檔需要有可執行的示例

本文所選取的方式為:基於測試工具抓包,測試數據真實、由專業的測試人員定制、容易獲取和更新(替換)、是常規的自動化回歸的思路

需要解決的問題:

  • 批量抓包導出的請求list中,可能包含部分不需要被回放的請求,如何自動剔除
  • Fiddler導出的txt和Charles導出的trace,文本格式標准化但有差異,需要分別解析

Parrot的解法:拿來抓包(Fiddler .txt or Charles .trace),寫個配置(yaml record部分),執行recorder.py搞定

  • 配置支持select、ignore模式,可根據host(全部匹配)、url(部分匹配)進行篩選,默認錄制全部
  • parser會根據傳入文件的后綴自動判定為Fiddler or Charles抓包,分別進行解析,生成標准化的ini文件

步驟二:回放

有了錄制階段拿到的標准化數據后,對於單個請求的回放不難做,本項目主要是簡單封裝了python requests模塊來實現。

做過實際項目接口自動化的同學,通常面臨的場景遠不是單獨按照既定參數調用一個接口那么簡單,一般都會面臨如下問題:

  • 部分參數需要實時變動,例如請求傳參中可能包含“日期”,抓包拿到的日期等回放的時候可能就失效了
  • 部分參數需要基於依賴關系獲取,例如A接口Response中的某個key需要作為B接口的實時傳參,單獨使用抓包的數據是無效的
  • 部分接口需要拿到特定結果后才能繼續執行,抓包時可能A接口較快拿到了數據,回放時可能就不是這樣了,例如刷票行為
  • 多個接口的調用順序需要保證,這個相對容易處理,因為抓包中基本都會包含各接口的調用時間,Parrot可按照該次序和當時的時間間隔執行

Parrot的解法:寫個配置(yaml replay部分),執行replayer.py搞定

  • 配置支持replace模式,可進行純靜態替換(example => t.example),可進行動態替換(2019/05/01 => {{Today()}}
  • 依賴關系可以通過配置中的store和replace模式配合,例如:store配置apiA::resp::sign(執行到apiA接口時會自動將該值計入內存),replace配置apiB::{sign} => {get::resp::sign}(執行apiB接口之前會實時替換該傳參)
  • 配置中的wait模式,可使用time方式來配置apiA: 1(執行完apiA接口后,額外等待1秒),也可使用rule方式配置apiA::data.code: '==200'(執行完apiA接口檢查Response是否符合,不符合則重復執行A,直到符合或超出最大重試次數-global_conf中定義)
  • 一般項目的很多接口有前后執行順序要求或依賴關系,Parrot默認的回放方式為串行且遵循錄制的時間間隔;若無依賴關系,想並發執行的話,可自行修改config.py中的global_conf

Parrot回放完成后,同樣會生成標准化的ini數據文件,供后續的對比驗證使用。


步驟三:驗證

目前大不多數項目http接口的Response采用的都是json格式,Parrot的驗證邏輯即是對錄制的Response和回放執行拿到的Response進行json diff。

如果只是做全量的文本比較,直接采用兩個字符串進行相等匹配即可,但實際項目中極少如此,一般會面臨如下問題:

  • Response中存在部分不需要對比且經常變化的key,例如:timestamp、token、sign等,需要在對比時進行剔除
  • 部分接口的Response可能只需要比對關鍵的一些key就夠了,例如:status、code,其余信息無需關注
  • 部分接口的Response的某些key的值通過對比不足以驗證,希望進行額外的規則驗證,例如:某值>0,某list非空
  • 部分接口的Response的某些key的值是list或字典格式,作為通用工具在未知層級的情況下,如何寫個配置就能對比了

Parrot的解法:寫個配置(yaml check部分),執行checker.py搞定

  • 配置支持select、ignore模式,可選定/忽略Response中的部分key,可針對特定接口(部分匹配)或默認的全部,多層級寫法:data.key1、data.key1.key2[0].key3
  • 配置支持rule模式,可配置驗證規則,可針對特定接口(部分匹配)或默認的全部,例如:apiA::data.status: '==200'、apiB::data.list: '!= []'
  • 本項目的json diff的主要思路是,分別將錄制的預期Response和回放的實際Response json分別解析為層級深度為1的鍵值對,如:data.key1.key2[0].key3 = 1,如此可方便使用者進行更好的配置

Parrot的對比驗證會輸出html report,其中可見如下信息:

  • 匯總信息,總條數、成功多少、失敗多少
  • 每條請求的status(http狀態碼)對比結果,duration(請求耗時)對比結果,response(響應信息)對比結果,request的詳情

以上

文字功底所限,可能尚有很多細節未描述清楚,歡迎留言交流;

Parrot項目已開源,代碼粗糙,歡迎大神提改進建議。

最后,再次附一下地址:https://github.com/idle-man/Parrot 

願意的話,不妨給個Star~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM