楊玉環,圣文順,劉進芬
(南京工業大學浦江學院,江蘇南京 211200)
信息系統上線后通常需要迭代升級或者重構,并進一步保證被修改后系統中原有業務的正確性。簡單的業務系統可以通過常規的自動化測試工具及人工測試來保證,但對于業務復雜的系統,回歸測試是一項浩大的工程。比如各種網購軟件需要時刻為用戶提供查看、購買、退訂等服務,其穩定性非常重要。為了吸引更多的用戶,增加用戶粘性,這些流行的軟件都要進行頻繁的優化升級。
軟件測試是軟件質量保證的重要手段,軟件測試從執行方式上分為手動測試和自動化測試。快速迭代和快速交付迫使人們希望通過自動化測試來提高效率[1]。回歸測試是指修改了原有代碼后重新進行測試,以確定修改沒有引入新的錯誤或導致其他代碼產生錯誤[2]。相對于手動回歸測試,自動回歸測試可以大幅降低軟件研發過程中的升級與重構成本。每次全面升級,都要進行回歸測試,其工作量及困難程度之大可想而知。常規的自動化測試工具需要準備測試數據,編寫腳本,加上覆蓋率不高,因此無法滿足重構后的回歸驗證要求。雖然可以通過計算回歸測試路徑優先級,選擇性的執行優先級高的測試用例,但商用的軟件不能放過任何一個功能測試點,要做到測試全覆蓋[3]。近幾年流行基于mock 技術實現接口的自動化測試,豐富了自動化測試分層的框架,提高了接口程序自動化守護的質量[4]。或對傳統軟件開發中的mock 測試技術進行改進,并提出Web 應用下mock 自動化測試工具的系統架構[5-6]。或將測試系統架構進行重構,以自動生成測試用例并處理高并發的請求[7-10]。或開發出軟件測試框架需要支持自動生成內含各測試用例細節描述及對應結果等信息的測試結果文件,支持以Web 頁面形式對測試結果進行個性化展示與瀏覽[11]。但如上都只能解決局部的問題,所設計的Dack 導流測試平臺實現了自動收集用戶請求,并將請求自動轉化為測試用例,解決了測試覆蓋率低,測試執行效率低的問題,通過復制線上真實流量進行自動回歸測試。在該平臺的使用過程中發現了很多重構帶來的bug,從而提高了重構軟件的質量并加快了重構項目的上線進程。
Dack 平臺為了應對復雜的業務需求,使用微服務架構來實現[15-18]。其主要功能是收集線上真實用戶的流量,將這些流量中的請求和響應存入數據庫,并在回歸測試時將這部分流量進行回放,以驗證更新后系統的功能。所謂線上流量是指軟件系統發布并商用后,真實的用戶使用該軟件所產生的請求響應消息。其原理圖如圖1 所示。

圖1 Dack平臺原理圖
線上的用戶請求中不可避免地攜帶真實用戶的信息,所以需要在復制流量時進行脫敏[12-13],對敏感信息進行分組和匿名化處理。為防止侵犯用戶的隱私,該系統對用戶的賬號、地址等敏感信息進行掩碼處理。
對于每日上億條的Web 請求和響應的寫入和讀取,需要數據庫支持較高的吞吐量以及靈活的可擴展性,系統使用mongoDB 數據庫,其中數據以json 文檔存放,來保證整個項目的數據使用統一的模型,避免數據轉換,提高了在回放過程中比對工作的效率。Dack 平臺借鑒了文獻[14]中的索引和查詢優化的方法,使得在上億條數據記錄中的查詢每秒可以完成8 000~9 000 次。
通過將在線流量直接轉化為測試用例,大量的真實流量保證了接口高覆蓋率的同時,減少了測試設計的工作,使測試人員有更多的時間去分析測試結果從而發現并上報更多的bug。對于測試用例的執行,可以手動觸發,也可以定時觸發,保證了用例執行的靈活性。對于Web 應用的測試,一般通過發起http 請求的方式來完成,從線上獲取的真實請求被回放到測試環境中,即向測試環境發起同樣的請求,然后對線上的響應消息和測試環境的響應消息進行全量對比,發現其中的差別,從而識別系統的問題。默認情況下,完全相同即認為用例通過,而對于無需比對的條目或者確定要刪除或增加的條目,可以在用例配置模塊中進行配置,忽略該條目,不影響用例執行結果。
Dack 平臺通過在網絡層錄制流量,獲取的內容包括:1)用戶請求的url 以及參數名字和參數值,參數支持key=value 的格式,以及json 格式。2)系統返回的響應消息,其中包含return code,響應消息體,然后進行請求回放。其應用場景如圖2 所示。

圖2 Dack平臺應用場景
該平臺可以在日常的自動化接口測試時使用,也可以在開發人員每日提交了持續集成的代碼后觸發,還可以在系統重構后手動觸發,適合多種測試場景,又因測試用例都是自動化用例,相比較于手動用例,執行效率要高很多。在日常開發過程中,當需要確定新增加的代碼對其他模塊功能沒有影響時,可以手動一鍵觸發自動化測試任務,批量執行選定的測試用例。在自動化接口測試階段,被測系統的接口功能需要進行測試,它可以通過執行測試人員編寫的測試用例或Dack 平臺提供的測試用例來完成。對于重構測試,使用在線流量錄制請求的回放,更容易發現重構代碼中的bug。
測試執行都是從測試用例開始的,Dack 平臺采用復制流量的思想,基于服務器也就是在應用層對請求進行復制,相對于在IP 層復制流量后的諸多修改以及后期復雜的運維,其優勢在于實現簡單,它的測試結果也更真實。Dack 平臺復制的http 在線流量會被存儲到mongoDB 數據庫中,一個http 請求報文可以由請求行、請求頭、空行和請求體4 個部分組成,其中請求行由三部分組成:請求方式、請求資源的路徑、http 協議的版本。Dack 平臺主要處理GET方式的請求和POST 方式的請求,其中GET 方式的請求只有請求行、請求頭、空行,沒有請求體,因為它只是從服務器獲取信息,而POST 方式的請求包含如上所說的http 請求報文的4 個部分。
Dack 平臺根據url 信息,對于GET 請求,首先分離出方法名作為用例名稱,把請求行中以&連接的key=value 形式的參數分離出來,作為測試用例的輸入數據,json 格式的響應結果作為測試結果直接存儲在mongoDB 中;對于POST 請求,用例名稱和測試結果的分離方式與GET 請求相同,但請求行中的參數同時支持key=value 的parameter 格式和json 格式,這對于Dack 自動生成的測試用例沒有影響,但對于需要手動添加的用例,需要指明是parameter 格式還是json 格式。
觸發單條或多條用例時,Dack 平臺從mongoDB中拉取一條預先存放的在線請求及響應結果,并向測試環境中的服務器回放該請求,然后將測試結果與在線的響應結果做全量比對,得出執行成功或失敗的測試結果。以查看某一應用為例,回放的過程如下:
DServiceImpl.execute(realBody)//測試用例觸發回放
expectResult.setR(realBody)//確定期望結果
detailService.get(realParam)//設定請求參數
detailDaoImpl.search(realParam)//執行查詢操作
DServiceImpl.execute(expectResult,testBody)//執行比對操作,得到用例執行結果
以查詢應用詳情接口為例,將用戶查詢應用詳情過程中的參數保存下來,在回放時把參數添加到請求消息中,然后發送請求到測試環境中的Web 服務器,獲取查詢請求的響應結果,收集及回放流量過程如圖3 所示。

圖3 收集及回放流量過程
在線請求的錄制根據url 和參數來區分不同的請求,當用戶查看一個應用詳情時,會產生5 個請求,它們的url 和參數相同。所以在測試環境中可以直接回放。在線請求通過測試用例觸發來回放,測試用例中url 和參數項是固定的,參數值在mongoDB中獲取,同樣對應用詳情的查詢請求,可以有千萬個不同的用戶產生千萬條不同的具體請求,在進行一鍵回放時,mongoDB 隨機選取一條來回放,以實現用例的多樣性。
對于測試人員,Dack 平臺屬于B/S 結構,用戶只需要通過瀏覽器的網頁進行項目添加、用例管理、參數配置、結果對比等操作;但對于平臺的服務端而言,它屬于C/S 結構,Client 端包含流量復制插件的路徑、緩存管理、數據庫管理等功能,Server 端包含任務管理、客戶端運行管理,通過消息隊列執行流量的獲取和回放、對比管理等,其架構圖如圖4 所示。

圖4 Dack平臺架構圖
Dack 平臺的前端提供友好且易操作的處理流程,從流量錄制后自動生成的測試用例到各種參數配置、流量回放操作以及對比的設置,結果展示簡潔明了。
流量錄制功能:主要完成錄制任務,內容包含錄制的服務器IP 地址、接口范圍、錄制的時間等。
對比設置功能:可設置特殊化對比規則,正常情況下,升級或重構后的系統,對于固定的一個接口,同樣的請求應該返回同樣的響應結果,但對于響應結果有改變的接口,就不能采用全對比的方式,而要做一些設置使升級前后的結果對比達到部分相同即可讓測試用例通過。
敏感信息配置功能:1)掩碼的方式,將保密性的信息使用如“*”、“#”等掩蓋起來;2)編碼或密文的方式,將認證信息改變后進行存儲。
回放IP 配置:支持將流量回放到不同的測試服務器上,支持設置代理等功能。
參數類型設置:Dack 平臺支持被測系統中,包含的http 請求及響應的參數有application/json,text/xml,并針對兩種類型做相應的解析處理。
針對使用Token 進行多用戶驗證的軟件系統,Dack 平臺提供“Token 獲取設置”,該功能為測試用例中的Token 部分提供實時獲取功能,以便用例能正常執行。基于Token 的身份驗證過程如下:1)用戶使用賬號和密碼登錄服務器;2)服務器驗證通過;3)服務器返回一個帶簽名的Token 到客戶端;4)客戶端存儲Token,并且后續每次訪問服務端都是用該Token 作為身份信息;5)服務器驗證Token,并返回相應的結果。Dack 平臺的“Token 獲取設置”就是測試人員通過對服務器身份驗證接口的調用來獲取當前用戶的Token,然后存儲在自定義的變量中,以便在測試用例中使用。
任務控制功能:提供創建定時任務/一次性任務,還可以進行一鍵觸發任務的操作;展示任務列表中各任務的狀態等。
運行統計和結果報告功能:展示任務中的總用例數、成功和失敗的用例數、任務的執行IP、執行持續時間等。
在對比分析中,展示在線請求及響應和在回放時的請求及響應,對于不同的地方進行高亮顯示,以方便測試人員分析定位問題。執行的成功或失敗的結果也以高亮展示。這里的對比設置,不同前面的對比規則設置,這里只做臨時性的忽略或刪除某個對比項,以改變測試用例執行結果,從而影響整個任務的測試用例的通過率。
流量錄制模塊作為一個插件安裝在在線服務器上,通過Java Invoke 和http Invoke 功能,以Java 切片的編程方式進行在線流量錄制,從而不僅支持外部接口的驗證,還可以對內部接口進行驗證,如訪問數據庫的入參和返回結果等,這些流量存放在配置文件中指定的測試數據庫mongoDB 上。對于一些在線流量超大的接口,如每天過億的請求,可以選擇設置百分比錄制來減小服務器的壓力。
Dack 平臺還通過IP 隔離和數據庫隔離功能,將在線環境和測試環境進行連接的同時保證它們互不干擾。回放模塊使用高吞吐量的發布訂閱消息系統kafka,完成從mongoDB 獲取待發送的請求并在測試系統回放的過程。回放模塊在mongoDB 前增加redis緩存,以提升查詢效率。
文中設計的自動回歸測試平臺基于在線流量自動生成測試用例,通過單個或批量測試用例的執行將在線流量回放到測試環境,平臺利用mongoDB、redis、kafka 等工具搭建了一個高吞吐量、易用的測試平臺。平臺通過全流量復制保證回歸測試的覆蓋率,同時一鍵回放功能提高了測試執行的便捷性。目前該平臺僅僅支持接口測試,對于界面的測試還需進一步研討開發。