如何確保API 的穩(wěn)定性與正確性?你只需要這一招
一、什么是rest-assured

現(xiàn)在,越來越多的 Web 應(yīng)用轉(zhuǎn)向了RESTful的架構(gòu),很多產(chǎn)品和應(yīng)用暴露給用戶的往往就是一組 REST API,這 樣有一個好處,用戶可以根據(jù)需要,調(diào)用不同的 API,整合出自己的應(yīng)用出來。從這個角度來講,Web 開發(fā)的成本會越來越低,人們不必再維護自己的信息孤島,而是使用 REST API 這種組合模式。
那么,作為 REST API 的提供者,如何確保 API 的穩(wěn)定性與正確性呢?全面系統(tǒng)的測試是必不可少的。Java 程 序員常常借助于 JUnit 來測試自己的 REST API,不,應(yīng)該這樣說,Java 程序員常常借助于JUnit 來測試 REST API的實現(xiàn)!從某種角度來說,這是一種“白盒測試”,Java 程序員清楚地知道正在測試的是哪個類、哪個方 法,而不是從用戶的角度出發(fā),測試的是哪個REST API。
Rest-Assured 是一套由 Java 實現(xiàn)的 REST API測試框架,它是一個輕量級的REST API 客戶端,可以直接編寫代碼向服務(wù)器端發(fā)起 HTTP請求,并驗證返回結(jié)果;它的語法非常簡潔,是一種專為測試 REST API 而設(shè)計的 DSL。使用 Rest-Assured 測試 REST API,就和真正的用戶使用 REST API 一樣,只不過 Rest-Assured 讓這一切變得自動化了。
二、模擬get請求
雪球網(wǎng)是一個股票投資網(wǎng)站,你可以使用網(wǎng)站的搜索功能來查詢股票信息,比如我們想查詢sougou的信息,下 面利用了charles分析工具來查看請求和回答:
這是一個Get請求,返回的內(nèi)容格式如下:
現(xiàn)在,我們使用 Rest-Assured 來編寫一個簡單的測試程序調(diào)用相同的Get請求:
第一步,我們要判斷這是什么格式數(shù)據(jù):json
第二步,確定請求地址:從charles的結(jié)果中獲取y為https://xueqiu.com/stock/search.json
第三步,填寫表單:從chrome瀏覽器檢查結(jié)果中查詢request的query信息是code:sougou
我們的代碼也很簡單:
返回的結(jié)果卻很殘酷:
與登陸賬號,刷新頁面有關(guān)的話,我首先想到了cookie,網(wǎng)站都用cookie來保存賬號相關(guān)信息,于是加入 cookie:
返回結(jié)果正確,你問我驚不驚喜,老實回答,不驚喜。因為我搞不明白為什么一個查詢需要cookie驗證,如果 不加cookie,返回的信息卻是沒有登陸!
顯然,我的cookie并不包含登陸信息,因為我壓根就沒有登陸,當然這是網(wǎng)站的設(shè)計,與rest-assured無關(guān)。
更進一步
怎么區(qū)別xml與json
答:你看就知道了嘛,xml長這個樣子
json長這個樣子
given,when,then分別是什么
答:given用于放置需要的參數(shù),比如上面例子中,我將訪問參數(shù):code和cookie放到了given里;when用于填 寫要訪問的url;then進行斷言,來來判斷結(jié)果是否正確。
三、模擬post請求
有的時候,我們想提交表單,這種情況下使用get會非常被動,于是post登場了。
下面是代碼。
我相信此時你的內(nèi)心是這樣的。
別著急,下面我會講清楚…
在我大萬維網(wǎng)世界中,TCP就像汽車,我們用TCP來運輸數(shù)據(jù),它很可靠,從來不會發(fā)生丟件少件的現(xiàn)象。但是 如果路上跑的全是看起來一模一樣的汽車,那這個世界看起來是一團混亂,非常緊急的警車可能被前面的汽車攔堵在路上,整個交通系統(tǒng)一定會癱瘓。
為了避免這種情況發(fā)生,交通規(guī)則HTTP誕生了。HTTP給汽車運輸設(shè)定了好幾個服務(wù)類別,有GET, POST, PUT, DELETE等等,HTTP規(guī)定,當執(zhí)行GET請求的時候,要給汽車貼上GET的標簽(設(shè)置method為GET),而且要求 把傳送的數(shù)據(jù)放在車頂上(url中)以方便記錄。如果是POST請求,就要在車上貼上POST的標簽,并把貨物放 在車廂里。當然,你也可以在GET的時候往車廂內(nèi)偷偷藏點貨物,但是這是很不光彩;也可以在POST的時候在車頂上也放一些數(shù)據(jù),讓人覺得傻乎乎的。HTTP只是個行為準則,而TCP才是GET和POST怎么實現(xiàn)的基本。
四、使用斷言
使用equalTo
在前面,我們使用了equalTo判斷值是否是“搜狗”:
它的作用顯而易見:判斷值是否相同。比如下面的例子
如果你想驗證lottoId是否等于5,你可以這樣做:
使用hasItems
你可以用再次equalTo(),對winnerId[0]用一次,對winnerId[1]用一次。
哈哈,當然不是。你可以使用hasItems,它是這么使用的:
從根開始定位
額…請教王師傅。
比如下面的代碼,我們可以這么驗證:
使用find
答對了,請一定要記住xml和json的區(qū)別,不要混談,那么你能編寫一個測試來驗證雜貨(groceries)的類別是 否包含巧克力(Chocolate)和咖啡(Coffe)嗎?
這確實達到了我的要求,但代碼明顯有很多bug,如果我更改了category的位置,像下面這樣,你的代碼就不 適用了,我不難為你了,請王師傅來解答吧:
find的用法展示的很清楚,不需要我多講,當然還有一點要注意,你可以這么使用find:
**是個特殊用法,它從xml文檔根部開始,進行深度搜索,直到找到符合我們需要的項。
使用findAll
現(xiàn)在我手頭只有20塊錢,我只能買兩本書,我更喜歡世紀的諺語和白鯨記,現(xiàn)在的任務(wù)是:挑選出格低于10的書籍,并且標題是“世紀的諺語(Sayings of the Century)”和“白鯨記(Moby Dick)”
對的,這時候應(yīng)該使用findAll,可以粗魯?shù)恼J為多個find的疊加。findAll可以篩選出一批符合要求的數(shù)據(jù),而 find只能篩選出一個符合要求的數(shù)據(jù),這就像是我們只能挑出一個人領(lǐng)取一等獎,但有很多人可以拿參與獎, 兩個方法都有自己的用武之地。
下面的代碼展示了findAll的用法:
五、提取想要的值
有時候,我們并不想驗證是否正確,我們只想取出這個值以進行下一步處理,比如我想取出next的鏈接:/title?page=2,這種情況怎么辦呢?
下面的代碼判斷內(nèi)容是不是JSON,并且標題是My Title的話,就返回href鏈接/title?page=2,這個值被存放在nextTitleLink中,以供我們以后使用。
當然,有兩點需要注意:
返回類型是Response,我們可以用Response.xxx來二次提取想要的值。
extract().后面是response()方法,不要寫錯了。
六、更改默認值
rest-assured有很多默認值,也正因為如此,需要我們的填的參數(shù)可以很少,也可以很多,就像畫畫一樣,可以很精致,也可以很簡潔。
修改端口
rest-assured發(fā)起請求時,默認使用的host為localhost,端口為8080,如果你想使用不同的端口,你可以這樣做:
或者是這樣
或者
修改baseURI和basePath
你也可能改變默認的baseURI、basePath
這就意味著,類似 get("/hello") 這樣的一個請求,其實完整的請求為:http://myhost.com:80/resource/hello , 并且使用基礎(chǔ)授權(quán)認證"username" and “password”。
其他
其他的默認值可以參考下面:
重置
你也可以重置為標準的baseURL(localhost)、basePath(空)、標準端口port(8080)、標準根路徑root path(" "),默 認的認證scheme(none)以及URL編碼(true),通過下面的方法重置:
七、specification
在不同的測試用例當中,我們可能會有重復(fù)的響應(yīng)斷言或者是請求參數(shù),那么我們可以將重復(fù)的這一部分提取出來定義一個規(guī)范或者模板,這樣的話在后續(xù)的測試用例當中就可以使用這個規(guī)范模板了。
為了達到這個效果,我們可以使用RequestSpecBuilder或 ResponseSpecBuilder來實現(xiàn),它們之間的區(qū)別 是,前者用在請求中,后者則用在body中。
ResponseSpecification重用
例如,你想在多個測試用例中,都使用這樣的斷言:判斷響應(yīng)狀態(tài)碼是否為200,并且Json數(shù)組"x.y"的大小是否 等于2。你可以定義一個ResponseSpecBuilder來實現(xiàn)這個功能:
在這個例子中,需要重用的兩個斷言數(shù)據(jù)被定義在"responseSpec",并且與另外一個body斷言合并,組成了這 個測試用例中全部的斷言,那么這個測試用例需要全部斷言都通過用例結(jié)果才會通過,一旦其中一個斷言失 敗,則測試用例的測試結(jié)果為失敗。
RequestSpecification重用
同樣,假如你想在多個測試用例中重用請求數(shù)據(jù),可以通過下面的代碼來實現(xiàn):
這里的請求數(shù)據(jù)被合并在"requestSpec"中,所以這個請求包含了兩個參數(shù)(“parameter1"和"parameter2”)以及一 個頭部(“header1”)。
總結(jié)
本文就rest-assured的基本功能進行舉例說明,其中例子大多來自于官方文檔,同時我也建議大家多去閱讀該開 發(fā)文檔,其中有很多我們沒有講到的東西。 本文參考: rest-assured官網(wǎng):https://github.com/rest-assured/rest-assured/wiki/Usage rest-assured介紹:https://www.ibm.com/developerworks/cn/java/j-lo-rest-assured/ get與post的區(qū)別:https://www.cnblogs.com/logsharing/p/8448446.htm
使用specification:https://www.cnblogs.com/lwjnicole/p/8277468.html
API
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。