劉國慶 汪興軒
(復(fù)旦大學(xué)信息科學(xué)與工程學(xué)院 上海 200433)
接口測試是指Web系統(tǒng)組件間的測試,它主要用于檢測組件與組件之間的交互點[1]。在移動軟件開發(fā)領(lǐng)域,大多采用分層軟件體系結(jié)構(gòu),服務(wù)提供者和消費者基于接口契約傳遞數(shù)據(jù)和上下文信息。應(yīng)用軟件的數(shù)據(jù)大多來源于服務(wù)端的接口返回,持續(xù)保障接口有效返回、及時發(fā)現(xiàn)異常接口是移動軟件測試中的一個重要課題[2]。
在Web應(yīng)用開發(fā)領(lǐng)域,客戶端服務(wù)器模型是一種被廣泛應(yīng)用的網(wǎng)絡(luò)架構(gòu),它把整套軟件系統(tǒng)劃分為客戶端和服務(wù)端[3],即客戶端請求數(shù)據(jù),服務(wù)端響應(yīng)內(nèi)容。超文本傳輸協(xié)議是一個基于請求與響應(yīng)的無狀態(tài)Web傳輸協(xié)議,因其具有傳輸效率高、占用較低的網(wǎng)絡(luò)帶寬等特點而被廣泛使用[4]。
Charles是一款被廣大Web開發(fā)者廣泛使用的HTTP/HTTPS代理服務(wù)器、監(jiān)視器、反向代理服務(wù)器軟件,當Web應(yīng)用程序通過Charles的代理訪問互聯(lián)網(wǎng)時,Charles可以監(jiān)控HTTP/HTTPS應(yīng)用程序發(fā)送和接收的所有數(shù)據(jù)。Charles允許開發(fā)者查看所有連接互聯(lián)網(wǎng)的HTTP/HTTPS通信,包括Request、Response以及Headers等,在Web開發(fā)中扮演著重要的角色。
傳統(tǒng)的HTTP接口測試需要測試人員手工設(shè)計用例與構(gòu)建參數(shù),利用接口測試工具,如postman、jmeter、fiddler等[5],模擬客戶端向服務(wù)端發(fā)送請求,服務(wù)端處理后返回請求結(jié)果,測試人員手工檢查返回的結(jié)果是否符合預(yù)期。傳統(tǒng)的測試工具雖然使用方便,易于上手,但是它們也有很多不足之處:
(1) 測試數(shù)據(jù)需手工輸入 接口測試本質(zhì)上是對接口輸入和輸出數(shù)據(jù)對應(yīng)關(guān)系的測試。測試人員手動調(diào)用接口,輸入測試數(shù)據(jù),然后驗證接口返回數(shù)據(jù)的正確性。每次接口測試之前,測試人員必須手動向工具輸入測試數(shù)據(jù),耗時耗力。
(2) 無法測試加密接口 接口測試工具無法自動執(zhí)行加解密操作,例如md5、base64、AES等加密方式。對于加密接口,測試人員需使用加解密工具對參數(shù)處理之后才能進行測試,導(dǎo)致測試效率低下。
(3) 擴展能力不足 接口測試工具雖然有它的便利性,但與此同時也伴隨著局限性。例如,測試人員需要將測試結(jié)果生成HTML形式的測試報告后發(fā)到指定的郵箱、需要對接口做持續(xù)集成測試等,這些都是工具難以做到的。
對應(yīng)客戶端服務(wù)端模型,在移動軟件測試領(lǐng)域中,基本上采用“端分離測試”的工作模式,即各端保障各端質(zhì)量[6]。實際上,客戶端工作時往往頻繁地調(diào)用服務(wù)端接口,獲得了大量的測試數(shù)據(jù),生成了豐富的測試用例。而“端分離測試”這種工作模式忽略了客戶端測試人員在測試過程產(chǎn)生的大量的服務(wù)端測試用例,從而導(dǎo)致了冗余的測試工作。
傳統(tǒng)的接口測試需要測試人員了解接口定義、設(shè)計測試用例、配置請求參數(shù)、觀察接口響應(yīng)等[7]。由于軟件開發(fā)中接口設(shè)計場景化、請求參數(shù)復(fù)雜化、服務(wù)端數(shù)據(jù)動態(tài)化等趨勢愈發(fā)明顯,人工觀察接口響應(yīng)容易出錯,上述步驟必然會導(dǎo)致測試效率不高。特別對于新開發(fā)的移動應(yīng)用軟件,必伴隨著大量的服務(wù)端接口,測試人員逐個測試接口,造成了大量的重復(fù)工作。
為此,本文提出了一種應(yīng)用于新開發(fā)移動應(yīng)用場景下,伴隨客戶端功能測試,基于Charles錄制會話的HTTP接口自動化測試框架。它依托于業(yè)界內(nèi)已有的開源持續(xù)集成平臺[8]和單元測試框架,從客戶端功能測試出發(fā),實現(xiàn)了自動生成測試用例、對測試數(shù)據(jù)自動處理、持續(xù)集成測試、生成測試報告等功能,測試人員在進行客戶端功能測試的同時收集服務(wù)端測試數(shù)據(jù)與用例,添加接口響應(yīng)校驗規(guī)則后,便可持續(xù)檢驗接口是否正常工作。
相較于傳統(tǒng)的接口測試工具與測試流程,本文提出的方案省去手工構(gòu)建請求參數(shù)環(huán)節(jié),實現(xiàn)自動構(gòu)建請求與校驗響應(yīng),增加集成測試與擴展功能,實現(xiàn)接口測試由人工到自動化的轉(zhuǎn)變,提高了測試效率。
如圖1所示,本文提出的接口自動化測試框架主要包含測試用例錄制單元、中間件服務(wù)單元以及持續(xù)集成測試單元三部分,每個單元又由不同的子單元構(gòu)成。
圖1 接口自動化測試框架系統(tǒng)架構(gòu)
(1) 測試用例錄制單元:客戶端監(jiān)聽工具(Charles):記錄HTTP會話,監(jiān)聽被調(diào)用接口傳遞的參數(shù),錄制接口測試用例,導(dǎo)出“.har”文件;
“.har”文件解析:提取會話數(shù)據(jù),生成測試用例;
測試用例池:存放測試用例、接口請求參數(shù)與校驗規(guī)則。
(2) 中間件服務(wù)單元:接口請求構(gòu)建:調(diào)用測試用例池中的接口Url、Method等參數(shù),構(gòu)建并向服務(wù)端發(fā)送接口請求;
接口響應(yīng)校驗:校驗接口響應(yīng)信息,檢查接口返回的數(shù)據(jù)結(jié)構(gòu)與值是否符合預(yù)期。
(3) 持續(xù)集成測試單元:單元測試框架:調(diào)用中間件服務(wù)單元,執(zhí)行測試用例,生成測試報告;
持續(xù)集成平臺:定時調(diào)用單元測試框架,自動化執(zhí)行接口測試,發(fā)送測試報告,如有異常則發(fā)送報警信息。
如圖2所示,當客戶端開發(fā)人員完成應(yīng)用開發(fā)并且轉(zhuǎn)交給測試人員后,測試人員在客戶端安裝待測應(yīng)用進行功能測試的同時,監(jiān)聽工具自動采集接口測試用例,具體流程如下:啟動Charles,客戶端連接代理服務(wù)器;測試人員進行客戶端功能測試,Charles錄制客戶端與服務(wù)端交互過程中所調(diào)用的接口以及傳遞的參數(shù)信息;通過調(diào)用Python腳本,提取Charles錄制的接口請求數(shù)據(jù),生成測試用例;測試人員完善測試用例并且添加接口響應(yīng)校驗規(guī)則后裝入單元測試框架;持續(xù)集成平臺以任務(wù)的形式定時運行單元測試框架,其分別完成向服務(wù)端發(fā)送接口請求數(shù)據(jù)、接收服務(wù)端響應(yīng)并與預(yù)先填寫的檢驗規(guī)則作對比、發(fā)送測試結(jié)果三項任務(wù)。
圖2 接口自動化測試框架工作流程
如圖3所示,在工程上,本文提出的接口自動化測試框架由Charles+Python+Unittest+Git+Jenkins構(gòu)成,主要分為兩部分:錄制接口測試用例與接口自動化測試。
圖3 接口自動化測試框架工程設(shè)計
如圖4所示,錄制接口測試用例部分以Charles為核心,Python腳本將HTTP會話過程轉(zhuǎn)換成可用的測試用例。測試人員在進行功能測試的同時,Charles錄制客戶端與服務(wù)端會話,測試結(jié)束后,導(dǎo)出“.har”格式文件。經(jīng)過白名單與黑名單過濾后,接口測試用例存入測試用例池。
圖4 接口測試用例錄制結(jié)構(gòu)
當客戶端連接Charles后,客戶端的請求參數(shù)通過Charles轉(zhuǎn)發(fā)至服務(wù)端,服務(wù)端的響應(yīng)又通過Charles下發(fā)至客戶端。如圖5所示,對于某款特定的移動應(yīng)用,其接口一般歸于一個或多個域名,而Charles將客戶端與服務(wù)端會話過程中所有的數(shù)據(jù)按照域名進行歸類,導(dǎo)出HTTP Archive(Har) format格式(“.har”)后,可查看會話詳情。
圖5 Charles代理服務(wù)器軟件
“.har”格式文件在本質(zhì)上是“utf-8”格式的json字符串文件,其中的“entries”字段為列表對象,保存了HTTP會話的詳情,一個元素則記錄了一條HTTP會話,“entries”的數(shù)據(jù)結(jié)構(gòu)如表1所示。
表1 “entries”數(shù)據(jù)結(jié)構(gòu)
從上一節(jié)得知,“entries”中的一個元素即可視為一條測試用例,而其中的“request”和“response”對象則保存了完整的請求與響應(yīng)信息。本文構(gòu)建了Python腳本將請求參數(shù)與響應(yīng)數(shù)據(jù)映射至測試用例池。測試用例根據(jù)接口的url字段歸檔,采用“一對多”的模式組織數(shù)據(jù)結(jié)構(gòu),即一個url對應(yīng)多組參數(shù),從而實現(xiàn)同一個接口對應(yīng)多個測試用例的組織模式。構(gòu)建測試用例池流程如圖6所示。
圖6 構(gòu)建測試用例流程圖
除了完整的請求與響應(yīng)信息以外,賦予測試用例名稱與編號,方便后期的維護與擴展。測試用例池的每條用例結(jié)構(gòu)如表2所示,其中headers、queryString、cookies、postData均為json對象。
表2 測試用例組織結(jié)構(gòu)
Python的xlrd和xlwt庫可以很方便地實現(xiàn)對Excel文件的寫入與讀取,而Excel表格可以直觀地顯示接口的信息以及請求的詳細數(shù)據(jù)。本文使用Excel文件作為測試用例池的存儲容器,一行為一條測試用例,而測試用例之間可能存在相同的請求對象,后期維護時可以較快擴展用例。
中間件服務(wù)用于連接用例池與服務(wù)端。它分為兩個部分,一部分是構(gòu)建單元,另一部分是接收單元。構(gòu)建單元負責將測試用例池中的用例參數(shù)組裝成HTTP請求并向服務(wù)端發(fā)送,待服務(wù)端解析請求后,接收單元接收接口響應(yīng)并將響應(yīng)報文轉(zhuǎn)換成預(yù)期的格式,與預(yù)先配置的校驗規(guī)則做對比。
構(gòu)建單元以Python的requests庫為基礎(chǔ),將測試用例中參數(shù)組裝成一個完整的HTTP請求。requests庫支持HTTP協(xié)議中的所有請求方法,并且其能攜帶所有的HTTP請求信息。
本主動托換體系設(shè)計的特點是受力明確、承載力可靠、變形易于控制、能夠適應(yīng)現(xiàn)有結(jié)構(gòu)布置和樁基布置條件、托換施工期間和托換完成以后的建筑物安全控制設(shè)計采取靜態(tài)應(yīng)變測試系統(tǒng)、電子位移計、傾角儀、裂縫觀測儀對新托換梁的撓度、沉降、傾斜度、裂縫進行高精度動態(tài)監(jiān)測,得出同步頂升時托換梁的即時變化結(jié)果,以便更準確地指導(dǎo)托換梁頂升工作。
服務(wù)端解析構(gòu)建單元的請求之后,會將響應(yīng)以Response對象的形式返回。而在移動應(yīng)用軟件開發(fā)中,大多數(shù)移動應(yīng)用基本采用json格式耦合客戶端與服務(wù)端。借助于Python中的json庫,將HTTP響應(yīng)報文轉(zhuǎn)換成json格式,方便校驗其響應(yīng)內(nèi)容。
本文將request庫和json庫進一步封裝,構(gòu)成基礎(chǔ)http請求包,以類方法的形式對外開放,用于傳遞HTTP數(shù)據(jù)。
類方法介紹如表3所示,Get_main和Post_main分別對應(yīng)HTTP協(xié)議中的Get和Post方法,Headers和Data若為空,則調(diào)用默認值,返回對象為統(tǒng)一的json格式的字符串。
表3 封裝HTTP請求方法
對于接口響應(yīng)內(nèi)容的校驗,本文選取了兩種校驗方式。對于無代碼能力的測試人員,使用Json Schema;另一種方式是使用斷言(Assert),而這也對測試人員提出了更高的要求。Json Schema指的是數(shù)據(jù)交換中的一種虛擬“合同”,用于Json數(shù)據(jù)的一致性檢驗。它可以驗證值的數(shù)據(jù)類型是否正確,是否包含所需的數(shù)據(jù),數(shù)據(jù)的組成結(jié)構(gòu)是否正確,值的范圍是否符合預(yù)期等。Python的jsonschema庫提供了豐富的json數(shù)據(jù)驗證功能,用戶僅僅需要將數(shù)據(jù)導(dǎo)入庫即可進行可靠的json驗證。在unittest框架中,TestCase類提供了較多的方法用于對接口響應(yīng)結(jié)果的校驗,表4列出了幾個常用的斷言方法。
表4 TestCase類常用斷言方法
持續(xù)測試單元由unittest單元測試框架、HTMLTest Runnner、Sendmail以及Jenkins構(gòu)成。其中unittest完成測試用例池中的用例組織與管理,HTMLTestRunner用于生成測試報告,Sendmail發(fā)送測試報告,而Jenkins則是整個持續(xù)測試的核心,它定期執(zhí)行測試任務(wù),實現(xiàn)接口測試框架的持續(xù)運行。
使用unittest單元測試框架組織管理測試用例池中的測試用例,執(zhí)行所有用例結(jié)束后利用HTMLTest Runner庫生成html格式的測試報告,同時構(gòu)建了SendMail模塊發(fā)送測試信息,便于遠程測試人員查看測試詳情。
unittest是一個Python單元測試框架,支持自動化測試,全局配置測試的開啟與關(guān)閉,測試用例以集合的形式聚合到框架中。unittest以類的形式組織測試用例,每一個測試類起始由“setup()”構(gòu)成,結(jié)束由“teardown()”構(gòu)成,中間包括各個測試用例“test_case()”。HTMLTestRunner配合unittest用于將測試結(jié)果保存至html文件中,提高可讀性。
在調(diào)用unittest單元測試框架時,測試用例必須以“test_”開頭。通過中間件服務(wù)單元將測試用例池中的用例以方法的形式實例化并嵌入至unittest單元測試框架。另外,unittest提供了完整的斷言方法,如果某個測試用例斷言失敗,框架則拋出“AssertionError”,并標識該用例測試失敗;否則,則標識該用例為測試成功狀態(tài)。例如assertEqual方法用于驗證兩個參數(shù)值是否相等,下述嵌入示例中的assertEqual驗證響應(yīng)結(jié)果的狀態(tài)碼是否為200,若不是則輸出“測試失敗”,并標記該用例為失敗狀態(tài);否則,測試用例通過。一個類中可定義多個測試用例函數(shù),按類分組批量執(zhí)行測試用例。嵌入示例及代碼結(jié)構(gòu)如下所示:
嵌入示例:利用assertEqual檢查接口的響應(yīng)狀態(tài)碼類名←繼承unittest中的TestCase類起始方法setUp測試用例函數(shù)func←傳入用例參數(shù)(來源于測試用例池) url←用例池中的Request.url header←用例池中的Request.headers data←用例池中的Request.data res←Get_main/Post_main(url, header, data) assertEqual(res[′status′], ′200′, ′測試失敗′)結(jié)束方法teardown
測試用例嵌入至unittest后,給定html文件的保存路徑以及測試報告名稱,完整的接口測試框架遍搭建完畢。unitest使用TestSuite管理測試用例,一個TestSuite是多個測試用例的集合,該集合內(nèi)的所有測試用例將被一起執(zhí)行。利用TestSuite可以將不同的測試用例組成測試邏輯組,即接口測試用例可根本被測軟件的邏輯功能進行模塊化組織,然后設(shè)置為統(tǒng)一的測試套件,對外僅暴露一個命令即可實現(xiàn)批量執(zhí)行測試用例。
接口自動化測試框架托管于遠程服務(wù)器中,為了方便查看測試報告,本文利用smtplib庫構(gòu)建了SendMail模塊集成至框架中,以郵件的形式發(fā)送測試報告?;玖鞒虨椋?/p>
1) 讀取測試報告;
2) 添加郵件內(nèi)容及附件;
3) 連接郵件服務(wù)器;
4) 發(fā)送郵件;
5) 退出。
框架定義list對象存儲郵件接收者信息,每個元素為接收者的郵箱地址,用于接收測試報告。測試報告以“MIMEText”格式集成至框架中,用戶設(shè)置本地郵箱和密碼后,建立 SMTP郵件服務(wù)器,啟動郵件發(fā)送流程,如發(fā)送異常,框架打印異常信息。
Jenkins平臺安裝Git插件后,將托管在Git服務(wù)器的代碼更新至測試環(huán)境后做持續(xù)集成測試。在配置Jenkins任務(wù)時選擇Git源碼管理,通過“Poll SCM”設(shè)定測試時間間隔,便可持續(xù)進行接口測試。值得注意的是,設(shè)定測試時間間隔忌太短,以免對服務(wù)端造成額外的壓力。每次測試結(jié)束后,Jenkins控制臺輸出測試信息,同時,測試報告以html形式存放于測試環(huán)境中的指定路徑。
在已部署接口自動化測試框架的測試機系統(tǒng)上,本文對一個Android開發(fā)應(yīng)用實施接口自動化測試。具體環(huán)境、測試過程、結(jié)果如下所述。
搭建基于CentOS 6.7 操作系統(tǒng)的的Linux測試環(huán)境, 部署本文提出的接口自動化測試框架??蚣苁褂肞ython 3.6.12版本編寫,依托于Jenkins 2.150.2版本持續(xù)集成運行。測試環(huán)境安裝Git命令行工具,Jenkins配置Git服務(wù)器地址并生成密鑰后與Git服務(wù)器建立連接。
如表5所示,本文對國內(nèi)某主流動漫社區(qū)安卓應(yīng)用進行冒煙測試,收集其一級按鈕下后端接口數(shù)據(jù)。首先使裝有待測應(yīng)用的客戶端連接Charles代理服務(wù)器,然后對移動應(yīng)用進行指定測試范圍內(nèi)的冒煙測試。測試結(jié)束后,Charles導(dǎo)出接口“.har”文件,經(jīng)過Python解析后,共獲取124個接口測試用例,部分測試用例數(shù)據(jù)如圖7、圖8所示。
表5 測試對象、方法、范圍
圖7 測試用例池記錄(1)
圖8 測試用例池記錄(2)
根據(jù)接口響應(yīng)數(shù)據(jù)格式以及接口數(shù)據(jù)結(jié)構(gòu)的不同,本文選取jsonschema與斷言兩種校驗方式交叉驗證接口數(shù)據(jù)是否正常返回。為上一小節(jié)測試用例池中的測試用例逐條添加校驗規(guī)則裝入unittest后,提交至Git服務(wù)器。
如表6的配置說明所述,在Jenkins平臺,配置Git服務(wù)器地址,以Python腳本的方式每5分鐘循環(huán)遍歷用例池中的用例,每條測試用例通過unittest向服務(wù)端發(fā)出請求,檢查響應(yīng)是否符合預(yù)期設(shè)定的校驗規(guī)則。單次遍歷接口用例結(jié)束后,生成一份html格式的測試報告,包括執(zhí)行用例時間、用例狀態(tài)、成功或失敗詳情等,如圖9所示。如圖10所示,在Jenkins中配置發(fā)送者與接收者郵箱后,測試結(jié)束后便可向指定郵箱發(fā)送測試報告。
表6 Jenkins配置說明
圖9 測試報告
圖10 發(fā)送測試報告
本文將提出的接口自動化測試框架在測試環(huán)境中運行24小時。郵箱以5分鐘為間隔收集測試報告,每份報告提供測試詳情。因接口返回數(shù)據(jù)動態(tài)變化,框架運行前期會出現(xiàn)因校驗規(guī)則設(shè)計不完整與接口響應(yīng)數(shù)據(jù)不匹配的現(xiàn)象,需及時修改校驗規(guī)則以兼容所有可能的接口并正確返回;運行后期,框架便可實現(xiàn)無人值守的接口自動化測試。
另外,本文對于某些接口設(shè)計了相應(yīng)的負向情況以檢驗框架的穩(wěn)定性,當框架運行異常時,如腳本錯誤、服務(wù)端響應(yīng)超時、測試任務(wù)異常等,Jenkins平臺可按照向預(yù)先設(shè)置的管理員郵箱發(fā)送報警郵件,并提供出錯的堆棧輸出。
本文提出了一種基于Charles錄制測試用例的HTTP接口自動化測試框架,它融合了現(xiàn)有接口測試工具的便利性,與此同時提高了測試效率。以功能測試為出發(fā)點,收集功能測試過程中的數(shù)據(jù),以此為基礎(chǔ)快速完善與補充測試用例,配合unittest框架和Jenkins平臺實現(xiàn)完整的接口自動化測試。通過實踐證明,工具在執(zhí)行自動化接口測試的同時,起到了一定程度的監(jiān)控作用,持續(xù)保證接口下發(fā)數(shù)據(jù)正常。
下一步的研究方向是增加參數(shù)列表,實現(xiàn)工具的自動構(gòu)建測試用例,進而提高接口測試效率以及保證接口測試的全面性。