web自動化測試之百度經驗-HTTP層面的Web Service自動化測試

前言java

咱們以前在測試web service的時候嘗試過多種方法:好比使用SoapUI;使用本地代理類編程等。前者不太方便作自動化,後者是從SOAP協議層面進行測試,數據組織不太方便,測試程序相對複雜,而且擴展性很差。python

SOAP協議大多使用HTTP綁定,咱們發現使用HTTP直接向web service server發送數據包能夠作到接口無關,不一樣的接口對於HTTP請求來講只是包的內容和目標url不一樣。這樣能夠將修改測試程序的工做轉變爲構造數據的工做,一方面在數據量較小的狀況下能夠減少測試準備和執行時間,另外一方面方便測試集成到持續集成環境中。web

SOAP層面的Web Service自動化測試編程

背景介紹api

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自動化測試方法一般是使用工具生成本地代理類,經過編程調用本地代理類實現自動化。這種測試方法數據構造簡單,可是測試程序稍複雜,擴展性不強。socket

數據組織分佈式

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的管理和執行一體化。

相關文章
相關標籤/搜索