楊玉環(huán),圣文順,劉進芬
(南京工業(yè)大學(xué)浦江學(xué)院,江蘇南京 211200)
信息系統(tǒng)上線后通常需要迭代升級或者重構(gòu),并進一步保證被修改后系統(tǒng)中原有業(yè)務(wù)的正確性。簡單的業(yè)務(wù)系統(tǒng)可以通過常規(guī)的自動化測試工具及人工測試來保證,但對于業(yè)務(wù)復(fù)雜的系統(tǒng),回歸測試是一項浩大的工程。比如各種網(wǎng)購軟件需要時刻為用戶提供查看、購買、退訂等服務(wù),其穩(wěn)定性非常重要。為了吸引更多的用戶,增加用戶粘性,這些流行的軟件都要進行頻繁的優(yōu)化升級。
軟件測試是軟件質(zhì)量保證的重要手段,軟件測試從執(zhí)行方式上分為手動測試和自動化測試??焖俚涂焖俳桓镀仁谷藗兿Mㄟ^自動化測試來提高效率[1]?;貧w測試是指修改了原有代碼后重新進行測試,以確定修改沒有引入新的錯誤或?qū)е缕渌a產(chǎn)生錯誤[2]。相對于手動回歸測試,自動回歸測試可以大幅降低軟件研發(fā)過程中的升級與重構(gòu)成本。每次全面升級,都要進行回歸測試,其工作量及困難程度之大可想而知。常規(guī)的自動化測試工具需要準(zhǔn)備測試數(shù)據(jù),編寫腳本,加上覆蓋率不高,因此無法滿足重構(gòu)后的回歸驗證要求。雖然可以通過計算回歸測試路徑優(yōu)先級,選擇性的執(zhí)行優(yōu)先級高的測試用例,但商用的軟件不能放過任何一個功能測試點,要做到測試全覆蓋[3]。近幾年流行基于mock 技術(shù)實現(xiàn)接口的自動化測試,豐富了自動化測試分層的框架,提高了接口程序自動化守護的質(zhì)量[4]?;?qū)鹘y(tǒng)軟件開發(fā)中的mock 測試技術(shù)進行改進,并提出Web 應(yīng)用下mock 自動化測試工具的系統(tǒng)架構(gòu)[5-6]。或?qū)y試系統(tǒng)架構(gòu)進行重構(gòu),以自動生成測試用例并處理高并發(fā)的請求[7-10]?;蜷_發(fā)出軟件測試框架需要支持自動生成內(nèi)含各測試用例細節(jié)描述及對應(yīng)結(jié)果等信息的測試結(jié)果文件,支持以Web 頁面形式對測試結(jié)果進行個性化展示與瀏覽[11]。但如上都只能解決局部的問題,所設(shè)計的Dack 導(dǎo)流測試平臺實現(xiàn)了自動收集用戶請求,并將請求自動轉(zhuǎn)化為測試用例,解決了測試覆蓋率低,測試執(zhí)行效率低的問題,通過復(fù)制線上真實流量進行自動回歸測試。在該平臺的使用過程中發(fā)現(xiàn)了很多重構(gòu)帶來的bug,從而提高了重構(gòu)軟件的質(zhì)量并加快了重構(gòu)項目的上線進程。
Dack 平臺為了應(yīng)對復(fù)雜的業(yè)務(wù)需求,使用微服務(wù)架構(gòu)來實現(xiàn)[15-18]。其主要功能是收集線上真實用戶的流量,將這些流量中的請求和響應(yīng)存入數(shù)據(jù)庫,并在回歸測試時將這部分流量進行回放,以驗證更新后系統(tǒng)的功能。所謂線上流量是指軟件系統(tǒng)發(fā)布并商用后,真實的用戶使用該軟件所產(chǎn)生的請求響應(yīng)消息。其原理圖如圖1 所示。
圖1 Dack平臺原理圖
線上的用戶請求中不可避免地攜帶真實用戶的信息,所以需要在復(fù)制流量時進行脫敏[12-13],對敏感信息進行分組和匿名化處理。為防止侵犯用戶的隱私,該系統(tǒng)對用戶的賬號、地址等敏感信息進行掩碼處理。
對于每日上億條的Web 請求和響應(yīng)的寫入和讀取,需要數(shù)據(jù)庫支持較高的吞吐量以及靈活的可擴展性,系統(tǒng)使用mongoDB 數(shù)據(jù)庫,其中數(shù)據(jù)以json 文檔存放,來保證整個項目的數(shù)據(jù)使用統(tǒng)一的模型,避免數(shù)據(jù)轉(zhuǎn)換,提高了在回放過程中比對工作的效率。Dack 平臺借鑒了文獻[14]中的索引和查詢優(yōu)化的方法,使得在上億條數(shù)據(jù)記錄中的查詢每秒可以完成8 000~9 000 次。
通過將在線流量直接轉(zhuǎn)化為測試用例,大量的真實流量保證了接口高覆蓋率的同時,減少了測試設(shè)計的工作,使測試人員有更多的時間去分析測試結(jié)果從而發(fā)現(xiàn)并上報更多的bug。對于測試用例的執(zhí)行,可以手動觸發(fā),也可以定時觸發(fā),保證了用例執(zhí)行的靈活性。對于Web 應(yīng)用的測試,一般通過發(fā)起http 請求的方式來完成,從線上獲取的真實請求被回放到測試環(huán)境中,即向測試環(huán)境發(fā)起同樣的請求,然后對線上的響應(yīng)消息和測試環(huán)境的響應(yīng)消息進行全量對比,發(fā)現(xiàn)其中的差別,從而識別系統(tǒng)的問題。默認情況下,完全相同即認為用例通過,而對于無需比對的條目或者確定要刪除或增加的條目,可以在用例配置模塊中進行配置,忽略該條目,不影響用例執(zhí)行結(jié)果。
Dack 平臺通過在網(wǎng)絡(luò)層錄制流量,獲取的內(nèi)容包括:1)用戶請求的url 以及參數(shù)名字和參數(shù)值,參數(shù)支持key=value 的格式,以及json 格式。2)系統(tǒng)返回的響應(yīng)消息,其中包含return code,響應(yīng)消息體,然后進行請求回放。其應(yīng)用場景如圖2 所示。
圖2 Dack平臺應(yīng)用場景
該平臺可以在日常的自動化接口測試時使用,也可以在開發(fā)人員每日提交了持續(xù)集成的代碼后觸發(fā),還可以在系統(tǒng)重構(gòu)后手動觸發(fā),適合多種測試場景,又因測試用例都是自動化用例,相比較于手動用例,執(zhí)行效率要高很多。在日常開發(fā)過程中,當(dāng)需要確定新增加的代碼對其他模塊功能沒有影響時,可以手動一鍵觸發(fā)自動化測試任務(wù),批量執(zhí)行選定的測試用例。在自動化接口測試階段,被測系統(tǒng)的接口功能需要進行測試,它可以通過執(zhí)行測試人員編寫的測試用例或Dack 平臺提供的測試用例來完成。對于重構(gòu)測試,使用在線流量錄制請求的回放,更容易發(fā)現(xiàn)重構(gòu)代碼中的bug。
測試執(zhí)行都是從測試用例開始的,Dack 平臺采用復(fù)制流量的思想,基于服務(wù)器也就是在應(yīng)用層對請求進行復(fù)制,相對于在IP 層復(fù)制流量后的諸多修改以及后期復(fù)雜的運維,其優(yōu)勢在于實現(xiàn)簡單,它的測試結(jié)果也更真實。Dack 平臺復(fù)制的http 在線流量會被存儲到mongoDB 數(shù)據(jù)庫中,一個http 請求報文可以由請求行、請求頭、空行和請求體4 個部分組成,其中請求行由三部分組成:請求方式、請求資源的路徑、http 協(xié)議的版本。Dack 平臺主要處理GET方式的請求和POST 方式的請求,其中GET 方式的請求只有請求行、請求頭、空行,沒有請求體,因為它只是從服務(wù)器獲取信息,而POST 方式的請求包含如上所說的http 請求報文的4 個部分。
Dack 平臺根據(jù)url 信息,對于GET 請求,首先分離出方法名作為用例名稱,把請求行中以&連接的key=value 形式的參數(shù)分離出來,作為測試用例的輸入數(shù)據(jù),json 格式的響應(yīng)結(jié)果作為測試結(jié)果直接存儲在mongoDB 中;對于POST 請求,用例名稱和測試結(jié)果的分離方式與GET 請求相同,但請求行中的參數(shù)同時支持key=value 的parameter 格式和json 格式,這對于Dack 自動生成的測試用例沒有影響,但對于需要手動添加的用例,需要指明是parameter 格式還是json 格式。
觸發(fā)單條或多條用例時,Dack 平臺從mongoDB中拉取一條預(yù)先存放的在線請求及響應(yīng)結(jié)果,并向測試環(huán)境中的服務(wù)器回放該請求,然后將測試結(jié)果與在線的響應(yīng)結(jié)果做全量比對,得出執(zhí)行成功或失敗的測試結(jié)果。以查看某一應(yīng)用為例,回放的過程如下:
DServiceImpl.execute(realBody)//測試用例觸發(fā)回放
expectResult.setR(realBody)//確定期望結(jié)果
detailService.get(realParam)//設(shè)定請求參數(shù)
detailDaoImpl.search(realParam)//執(zhí)行查詢操作
DServiceImpl.execute(expectResult,testBody)//執(zhí)行比對操作,得到用例執(zhí)行結(jié)果
以查詢應(yīng)用詳情接口為例,將用戶查詢應(yīng)用詳情過程中的參數(shù)保存下來,在回放時把參數(shù)添加到請求消息中,然后發(fā)送請求到測試環(huán)境中的Web 服務(wù)器,獲取查詢請求的響應(yīng)結(jié)果,收集及回放流量過程如圖3 所示。
圖3 收集及回放流量過程
在線請求的錄制根據(jù)url 和參數(shù)來區(qū)分不同的請求,當(dāng)用戶查看一個應(yīng)用詳情時,會產(chǎn)生5 個請求,它們的url 和參數(shù)相同。所以在測試環(huán)境中可以直接回放。在線請求通過測試用例觸發(fā)來回放,測試用例中url 和參數(shù)項是固定的,參數(shù)值在mongoDB中獲取,同樣對應(yīng)用詳情的查詢請求,可以有千萬個不同的用戶產(chǎn)生千萬條不同的具體請求,在進行一鍵回放時,mongoDB 隨機選取一條來回放,以實現(xiàn)用例的多樣性。
對于測試人員,Dack 平臺屬于B/S 結(jié)構(gòu),用戶只需要通過瀏覽器的網(wǎng)頁進行項目添加、用例管理、參數(shù)配置、結(jié)果對比等操作;但對于平臺的服務(wù)端而言,它屬于C/S 結(jié)構(gòu),Client 端包含流量復(fù)制插件的路徑、緩存管理、數(shù)據(jù)庫管理等功能,Server 端包含任務(wù)管理、客戶端運行管理,通過消息隊列執(zhí)行流量的獲取和回放、對比管理等,其架構(gòu)圖如圖4 所示。
圖4 Dack平臺架構(gòu)圖
Dack 平臺的前端提供友好且易操作的處理流程,從流量錄制后自動生成的測試用例到各種參數(shù)配置、流量回放操作以及對比的設(shè)置,結(jié)果展示簡潔明了。
流量錄制功能:主要完成錄制任務(wù),內(nèi)容包含錄制的服務(wù)器IP 地址、接口范圍、錄制的時間等。
對比設(shè)置功能:可設(shè)置特殊化對比規(guī)則,正常情況下,升級或重構(gòu)后的系統(tǒng),對于固定的一個接口,同樣的請求應(yīng)該返回同樣的響應(yīng)結(jié)果,但對于響應(yīng)結(jié)果有改變的接口,就不能采用全對比的方式,而要做一些設(shè)置使升級前后的結(jié)果對比達到部分相同即可讓測試用例通過。
敏感信息配置功能:1)掩碼的方式,將保密性的信息使用如“*”、“#”等掩蓋起來;2)編碼或密文的方式,將認證信息改變后進行存儲。
回放IP 配置:支持將流量回放到不同的測試服務(wù)器上,支持設(shè)置代理等功能。
參數(shù)類型設(shè)置:Dack 平臺支持被測系統(tǒng)中,包含的http 請求及響應(yīng)的參數(shù)有application/json,text/xml,并針對兩種類型做相應(yīng)的解析處理。
針對使用Token 進行多用戶驗證的軟件系統(tǒng),Dack 平臺提供“Token 獲取設(shè)置”,該功能為測試用例中的Token 部分提供實時獲取功能,以便用例能正常執(zhí)行?;赥oken 的身份驗證過程如下:1)用戶使用賬號和密碼登錄服務(wù)器;2)服務(wù)器驗證通過;3)服務(wù)器返回一個帶簽名的Token 到客戶端;4)客戶端存儲Token,并且后續(xù)每次訪問服務(wù)端都是用該Token 作為身份信息;5)服務(wù)器驗證Token,并返回相應(yīng)的結(jié)果。Dack 平臺的“Token 獲取設(shè)置”就是測試人員通過對服務(wù)器身份驗證接口的調(diào)用來獲取當(dāng)前用戶的Token,然后存儲在自定義的變量中,以便在測試用例中使用。
任務(wù)控制功能:提供創(chuàng)建定時任務(wù)/一次性任務(wù),還可以進行一鍵觸發(fā)任務(wù)的操作;展示任務(wù)列表中各任務(wù)的狀態(tài)等。
運行統(tǒng)計和結(jié)果報告功能:展示任務(wù)中的總用例數(shù)、成功和失敗的用例數(shù)、任務(wù)的執(zhí)行IP、執(zhí)行持續(xù)時間等。
在對比分析中,展示在線請求及響應(yīng)和在回放時的請求及響應(yīng),對于不同的地方進行高亮顯示,以方便測試人員分析定位問題。執(zhí)行的成功或失敗的結(jié)果也以高亮展示。這里的對比設(shè)置,不同前面的對比規(guī)則設(shè)置,這里只做臨時性的忽略或刪除某個對比項,以改變測試用例執(zhí)行結(jié)果,從而影響整個任務(wù)的測試用例的通過率。
流量錄制模塊作為一個插件安裝在在線服務(wù)器上,通過Java Invoke 和http Invoke 功能,以Java 切片的編程方式進行在線流量錄制,從而不僅支持外部接口的驗證,還可以對內(nèi)部接口進行驗證,如訪問數(shù)據(jù)庫的入?yún)⒑头祷亟Y(jié)果等,這些流量存放在配置文件中指定的測試數(shù)據(jù)庫mongoDB 上。對于一些在線流量超大的接口,如每天過億的請求,可以選擇設(shè)置百分比錄制來減小服務(wù)器的壓力。
Dack 平臺還通過IP 隔離和數(shù)據(jù)庫隔離功能,將在線環(huán)境和測試環(huán)境進行連接的同時保證它們互不干擾。回放模塊使用高吞吐量的發(fā)布訂閱消息系統(tǒng)kafka,完成從mongoDB 獲取待發(fā)送的請求并在測試系統(tǒng)回放的過程?;胤拍K在mongoDB 前增加redis緩存,以提升查詢效率。
文中設(shè)計的自動回歸測試平臺基于在線流量自動生成測試用例,通過單個或批量測試用例的執(zhí)行將在線流量回放到測試環(huán)境,平臺利用mongoDB、redis、kafka 等工具搭建了一個高吞吐量、易用的測試平臺。平臺通過全流量復(fù)制保證回歸測試的覆蓋率,同時一鍵回放功能提高了測試執(zhí)行的便捷性。目前該平臺僅僅支持接口測試,對于界面的測試還需進一步研討開發(fā)。