web自动化测试之百度经验-HTTP层面的Web Service自动化测试
2019獨角獸企業重金招聘Python工程師標準>>>
前言
我們之前在測試web service的時候嘗試過多種方法:比如使用SoapUI;使用本地代理類編程等。前者不太方便做自動化,后者是從SOAP協議層面進行測試,數據組織不太方便,測試程序相對復雜,并且擴展性不好。
SOAP協議大多使用HTTP綁定,我們發現使用HTTP直接向web service server發送數據包可以做到接口無關,不同的接口對于HTTP請求來說只是包的內容和目標url不同。這樣可以將修改測試程序的工作轉變為構造數據的工作,一方面在數據量較小的情況下可以減小測試準備和執行時間,另一方面方便測試集成到持續集成環境中。
SOAP層面的Web Service自動化測試
背景介紹
Web Service 是一種新的web應用程序分支,他們是自包含、自描述、模塊化的應用,可以發布、定位、通過web調用。Web Service通過WSDL(Web Services Description Language)文件發布。
SOAP是簡單對象訪問協議,定義了一種跨平臺的分布式系統通信協議。SOAP需要綁定到更低層次的傳輸協議(比如HTTP、RMI、JMS)等。最常用的是HTTP綁定。大多數的Web Service實現是借助SOAP協議,因而通常的Web Service測試方法都是在SOAP協議層面進行測試。在SOAP層面上,每一個請求的數據包格式都是固定的,不同的接口使用不同格式的數據包,因而測試的時候需要針對不同的接口有不同的數據準備和測試執行的方法。
現有的SOAP層面的Web Service自動化測試方法通常是使用工具生成本地代理類,通過編程調用本地代理類實現自動化。這種測試方法數據構造簡單,但是測試程序稍復雜,擴展性不強。
數據組織
SOAP層面的自動化測試的數據組織就是準備本地類的參數和返回值。
1. 輸入數據
為了更清楚的了解輸入數據,這里給出了SoapUI的兩張圖:
?
圖1 接口一輸入
?
圖2 接口二輸入
這兩幅圖顯示了SOAP層面的輸入數據。AuthHeader是SOAP包的header,是所有接口共有的數據結構;getAccountInfoRequest和getChangedIdRequest是SOAP包的body,各自有不同的字段,type和startTime是真正需要針對每個接口準備的數據。
2. 期望輸出
同樣這里給出了兩張SOAP的圖:
?
圖3 接口一輸出
?
圖4 接口二輸出
輸出中的ResHeader也是SOAP包的header,是所有接口的公共輸出。getAccountInfoResponse和getChangedIdResponse是SOAP包的body,各自的字段是真正要準備的預期結果數據。
3.分析
從上面給出的例子可以看出,基于SOAP層面的數據組織,需要準備的數據就是本地類的輸入和輸出字段值,因而數據構造無需考慮SOAP包的格式,比較直觀和簡單。但是不同接口的字段個數不同,字段名稱和類型也不同,所以數據的讀取比較麻煩,要針對不同的接口有不同的數據讀取程序。
測試程序
測試程序包含本地代理類和調用代理類的程序。本地類的生成通常借助于工具(比如java的Axis2)。調用本地代理類的程序對于每個接口都不同,因為每個接口需要調用不同的函數,在接口比較多的情況下比較麻煩,并且接口有變動都需要修改本地類和測試程序。
結果對比
這里的結果就是本地函數的返回值。在輸入和期望輸出都讀入內存的情況下,結果對比很簡單,就是逐個字段比較期望輸出和實際輸出。
HTTP層面的Web Service自動化測試
HTTP層面的Web Service測試步驟比較簡單:準備數據,使用HTTP發送請求數據包,使用HTTP方式接受響應,解析響應并驗證結果。
數據組織
HTTP層面的數據是完整的SOAP包(由于大多數SOAP協議基于XML,所以實際上是一個XML包)。
1.輸入數據
比如之前的兩個接口,對應的輸入XML包分別是:
?
圖5 接口一輸入XML包
?
圖6 接口二輸入XML包
2.期望輸出
期望輸出同樣是兩個XML包,只是內容不同,這里就不再舉例。
3.分析
通過上面的例子可以看出,HTTP層面的數據就是一個個XML包。對比SOAP層面的數據構造,只知道幾個字段值并不能得到一個XML包,需要自己考慮這個XML包的格式。優點就是數據的讀取很簡單,只需要將整個XML文件的內容讀入內存即可。并且很方便構造錯誤格式的輸入。
測試程序
基于HTTP層面的測試程序很簡單:以輸入的SOAP包為body構造HTTP請求,發送給Web Service Server;接收響應,讀取響應的HTTP包的body(就是一個SOAP包)。從這個過程可以看出,所有接口的測試程序都一樣。因而新增加接口或者原有接口發生變化都不會影響測試程序。
結果對比
在HTTP層面上,輸入和輸出都是一個XML包。因而結果對比可以將輸入和輸出XML包讀入到兩個字符串中,進行字符串對比。
改進思路
根據上文的分析,HTTP層面的Web Service測試的優勢是數據格式靈活,易于讀取,測試程序擴展性強,可以適用于所有的接口。但是缺點也很明顯:數據構造麻煩,還容易格式出錯;結果對比比較機械,無法選擇性的對比某些字段(有時候返回結果中包含有時間相關的量,這個量在每次測試的時候返回值都是不一樣的,因而在結果對比的時候需要忽略這些字段)。針對這兩個缺點我做了相應的改進:
改進數據構造
數據構造的難點在于無法從幾個字段構造出符合格式的XML包。
首先我們分析輸入數據。再來看之前給出的兩個接口的輸入:
?
圖7 接口一輸入分析
?
圖8 接口二輸入分析
可以看出這兩個XML包有相同的部分,就是在圖中用紅色框起來的部分。這部分就是SOAP包的header。一個標準的SOAP包具有這樣的格式:
?
圖9 SOAP包格式分析
輸入Header部分通常包含用戶認證的信息,不同接口的Header格式都相同;Body保存的是真正的數據,各個接口不同。通常不同的接口使用的Header只有少量的幾個(通常只是用一個或者少量幾個用戶做測試),因此我們可以把Header部分的構造提取出來。以dr-api為例,輸入的Header主要有username、password和token三個字段(還有一個target字段是選填的),那么我們只需要準備幾組username/password/token即可。
輸入Body由于是接口相關的,沒有統一的方法構造。但是我們可以結合SoapUI工具手動構造,這樣比直接寫XML包更方便。參考圖1,是SoapUI界面的“Form”標簽內容。在這個標簽下輸入Body里需要填寫的字段值,然后選擇“XML”標簽,SoapUI會顯示出對應的發送XML包。從中拷貝出Body的內容保存到XXX.input.xml里即可。
輸出Header通常包含接口無關的信息,比如處理時間,操作數,錯誤代碼等等(至少從百度推廣API和google adwords API來看都是如此)。那么我們也可以將輸出Header提取出來,在準備數據的時候只需要給出幾個字段即可。由于不同接口的這幾個字段的名稱和類型都一樣,所以很方便程序讀取。
準備輸出Body也可以借助于SoapUI。但是和輸入Body的準備不同,后者只需要有wsdl文件即可構造,輸出Body需要Web Service已經提供,使用SoapUI發送一次請求得到返回,這樣才能得到輸出Body。因而實際中輸出Body的準備通常直接用手動的方式構造,不使用SoapUI。
改進結果對比
Web Service的測試中有相當一部分是測試錯誤代碼(以百度推廣API V2版本為例,現在一共有約300個錯誤代碼)。這樣的測試不需要關注返回包的Body,只需要關注返回包Header中的錯誤代碼,那么我們不需要專門構造預期輸出的XML包,只需要提供一個錯誤代碼即可。類似的,如果我們只關注返回包Header里的信息,那么就省去了構造預期輸出XML包的過程,結果對比也很簡單。
如果測試關注于業務數據,也就是返回包的Body部分,除了字符串對比之外暫時還沒有更好更通用的解決方法。
改進總結
改進的結果就是每個case的數據包含三個文件:input.xml、output.xml和一個配置文件properties。Input.xml包含了輸入包的Body,output.xml包含了輸出包的Body,配置文件則配置了輸入輸出的header,還有這個case對應的url等信息。
整體思路
總體思路如下:讀取所有case的數據,生成用例列表(包含用例數據和調用的接口);對每一個用例,使用http發送數據包,按照XML的解析方法解析返回SOAP包,進行結果驗證;使用ficus以用例列表為輸入進行數據驅動測試。如下圖所示:
?
圖10 測試整體思路
設計與實現
數據組織
數據組織的主要目的有兩點:一是做到自描述,通過數據可以得到輸入和期望輸出,還有請求的url;二是減少冗余數據,比如將soap的header信息提取出來。為了達到這兩個目的,我們使用了一個配置文件和一個數據文件夾。配置文件主要存放元數據和公用的數據,數據文件夾存放真正的分散的數據。配置文件的內容如下:
?
圖11 全局配置文件
配置文件的內容主要分為五個部分。A、D、E部分保存的是case無關的元數據,B和C保存的是通用的header數據。
A部分的數據有:整個web service的url前綴(圖中的“drapi.serviceUrl”),公用的soap header代號(圖中的“drapi.headersGroup”),所有service的代號(圖中的“drapi.servicesGroup”)。
B和C部分是兩個公用的header。Normal和editor是他們的代號,在A中給出。Dr-api用到的header信息主要有username/password/token/target,都在這里給出。這些header會被每個case引用。
D和E部分是兩個service。它們的代號在A中給出。每個service有三個字段:name表示service的名稱;url表示service的url后綴。
數據文件夾里保存的是每個case的數據。數據文件夾可以再進行分層:每個子目錄的名字就是上面提到的service的名字,那么該子目錄下所有case訪問的url都是這個service的url。每個case有XXX.input.xml、XXX.output.xml和XXX.properties三個文件表示,XXX表示case的名稱(為了應用到ficus中,XXX最好不帶空格,否則會被ficus分成數組)。
ficus數據驅動
數據驅動使用ficus的data_driven關鍵字。關于這個關鍵字可以參考FICUS_DataDriven。 這個關鍵字需要兩個主要的輸入:csv文件,執行單個case的關鍵字。Csv文件的每一行都表示一個case,data_driven會針對csv文件的每一行循環調用執行單個case的關鍵字。
我們需要對此編寫兩個關鍵字。第一個是讀取配置文件和數據文件夾生成csv文件。這個關鍵字首先會讀取公共的配置文件,得到service列表和輸入header列表;然后創建一個csv文件,包含這幾列:url,使用的Header名稱,case名稱,XXX.input.xml路徑,XXX.output.xml路徑和properties中的字段。讀取數據文件夾的每個數據文件,根據XXX.input.xml/XXX.output.xml/XXX.properties的組合來添加case到csv文件中。
第二個關鍵字是用來執行單個case。輸入就是csv文件的一行。首先根據使用的Header和XXX.input.xml拼裝成輸入的XML包,使用HTTP方式向Web Service Server發送請求,接收HTTP相應,解析出Header和Body,將Header中個字段和XXX.properties中的個字段做對比,將Body和XXX.output.xml做對比。
ficus調用java關鍵字
我們寫關鍵字使用的是Java,這里簡單提一下如何用ficus調用java關鍵字(感謝朱雷同學的幫助)。在最新版的ficus程序里,有一個Java目錄,有一個ficus-java-stub.bat文件。將自己寫的java關鍵字打成jar包,放到這個目錄,然后啟動這個文件就可以啟動ficus的Java樁。在寫case的時候,首先要添加library,為了使用Java樁,需要添加FicusProxy.JavaProxy | XXX | YYY | localhost | 2345。XXX和YYY都是java關鍵字所在的public類的類名,這些類的public方法名稱都是ficus關鍵字。
它的原理是:FicusProxy.JavaProxy是一個python關鍵字,當ficus遇到一個關鍵字的時候,會通過JavaProxy來查詢。JavaProxy會通過socket發送請求到Java樁。Java樁加載了java關鍵字所在的jar包,因而可以通過反射找到以關鍵字為名字的方法,從而實現調用。
提示一點,如果自定義的java關鍵字(都是java方法)所在的類比較多,那么最好把FicusProxy.py的BaseProxy的_receive函數的length默認值改大一點兒,這個值表示ficus和Java樁通信每次發送的數據長度。如果太小,發送的數據會被截斷,包含關鍵字名稱和參數那部分會被截斷,就會出錯。
總結
以上便是我們在HTTP層面進行Web Service測試的總結。這種方法由于需要手動構造輸入和輸出SOAP包的body,因而在數據量較小并且不關注輸出包body的場景使用起來很方便。由于使用的數據驅動,也很方便應對接口的變動。
后續考慮遷移到eFicus中,實現case的管理和執行一體化。
轉載于:https://my.oschina.net/u/224865/blog/516752
總結
以上是生活随笔為你收集整理的web自动化测试之百度经验-HTTP层面的Web Service自动化测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: rhel7 http实例2
- 下一篇: JAVA成员变量为什么不能在类体中先定义