一文搞定 Postman 接口自動化測試

本文適合已經(jīng)掌握?Postman
?基本用法的讀者,即對接口相關概念有一定了解、已經(jīng)會使用?Postman
?進行模擬請求等基本操作。
工作環(huán)境與版本:
Window 7(64位)
Postman (Chrome App v5.5.3)
P.S. 不同版本頁面 UI 和部分功能位置會有點不同,不過影響不大。
首先我們來思考一下,如果要達到自動化接口測試效果,在基本的模擬請求上還需要做哪些呢?
我粗略概括為 3 個問題(歡迎在評論區(qū)留言更多補充建議):
1. 如何判斷接口是否請求成功?
2. 如何進行接口批量、定期測試?
3. 如何處理依賴接口問題(比如商品下單的接口必須要求先登錄)?
所以,接下來就主要分為 3 個部分,介紹如何解決這 3 個問題。
接口結果判斷

首先,既然是自動化測試,那么我們肯定需要通過工具?Postman
?或者代碼,幫我們直接判斷結果是否符合預期。那么在接口測試上,大體就兩個思路:
1.? 判斷請求返回的?code
?是否符合預期
2.? 判斷請求返回的內(nèi)容中是否包含預期的內(nèi)容(關鍵字)
接下來我們看看如何利用?Postman
?來解決上述的問題:
1.1 功能區(qū)

在?Postman
?中相關的功能在非常顯眼的地方,Tests
?功能的使用需要我們有一定的編程語言基礎,目前支持的腳本語言即為?JavaScript
?。但比較好的一點是,我們不需要再去考慮上下文問題以及運行環(huán)境的問題 ,也就是說我們只需要在這邊完成結果邏輯判斷的代碼塊即可。
而?Postman
?還為我們提供了一些常用的代碼模板,在?Tests
?面板右邊的?SNIPPETS
?功能區(qū)中,所以對?JavaScript
?不大了解問題也不大。代碼編寫相關將在下文進行具體介紹。
1.2 腳本相關
先看上圖的代碼部分,我們可以發(fā)現(xiàn)?responseCode
?、?responseBody
?和?tests
?三個變量(可直接使用) :
responseCode
?:包含請求的返回的狀態(tài)信息(如:code)。responseBody
:為接口請求放回的數(shù)據(jù)內(nèi)容(類型為字符串)。tests
?:為鍵值對形式,用于表示我們的測試結果是成功與否,最終展示在?Test Results
?中。key :(如:code 200)我們可以用來當做結果的一個描述。
value:其值為布爾型,
ture
?表示測試通過,?false
?表示測試失敗。
所以上述代碼應該不難理解了,而有了返回結果的數(shù)據(jù)以及表示結果成功與否的方式,那么我們“接口結果判斷”的問題也就基本解決了。
另外還有幾個比較常用的:
responseTime
?:請求所耗時長postman
?:可以做的比較多,比如獲取返回數(shù)據(jù)的頭部信息:
`postman.getResponseHeader("")`設置全局變量:
`postman.setGlobalVariable("variable_key", "variable_value");`
更多功能可以查看官方文檔。
1.3 代碼模板
Postman
?在?SNIPPETS
?功能區(qū)中為我們提供的代碼模板已經(jīng)能解決大部分情況了,以下先挑幾個跟結果判斷相關的進行講解:
Status code : Code is 200
//根據(jù)返回的?Code?判斷請求情況?
tests["Status?code?is?200"]?=?responseCode.code?===?200;??
Response body: Contains string
//判斷返回的內(nèi)容中是否存在“關鍵字”。(tests 的 key 可修改,將不再強調(diào))??
tests["Body?matches?string"]?=?responseBody.has("這里可以改為你要判斷的關鍵字內(nèi)容");????
//如上文提到的:
//判斷結果中是否存在?access_token?關鍵字
tests["has?access_token"]?=?responseBody.has("access_token");
Response body: is equal to string
//判斷返回內(nèi)容是否跟預期完全相等。
tests["Body?is?correct"]?=?responseBody?===?"這里可以改為你的預期內(nèi)容";
Response body: JSON value check
//上文提到,responseBody?為字符串類型,支持轉為?Json?格式
var?jsonData?=?JSON.parse(responseBody);
tests["Your?test?name"]?=?jsonData.value?===?100;
Response time is less than 200ms
//判斷請求時長是否小于200ms?,具體時長按情況自定義
tests["Response?time?is?less?than?200ms"]?=?responseTime?<?200;
以上介紹的這些基本已經(jīng)足夠完成對單一接口的測試了,但我們知道如果沒有批量、定時任務, 那么這些都將毫無意義,所以繼續(xù) …
集合(批量)測試

想要進行接口的批量測試、管理,那么我們需要將待測試的接口全部都保存到同一個集合(Collections)
中,你可以認為就是保存到同一個文件夾中。先看看?Postman
?中的操作步驟:

通過以上步驟,我們得到一個待測的接口集合,為了簡化情況,我這邊每個接口成功與否的條件都是用?code
?是否為 200 來判斷:
tests["Status?code?is?200"]?=?responseCode.code?===?200;
2.1 批量執(zhí)行
以上準備就緒后,我們就可以開始批量運行接口進行測試了:

點擊Run
?后,會新打開一個頁面:

Environment
?:用于切換接口運行的環(huán)境,這里先不管,后面再講Iteration
?:用于設置接口一共要運行的次數(shù)。Delay
?: 設置每次運行接口之間的時間間隔,單位為毫秒。Data File
?: 上傳測試數(shù)據(jù)文件 (下文單獨講)
2.2 變化的參數(shù)數(shù)據(jù)
我們已經(jīng)了解了,如何讓多個接口循環(huán)運行多次,但是現(xiàn)在有個問題,按目前這個步驟,每次運行時接口的參數(shù)都是一樣的,那么就算我們運行個100次、1000次意義也不大。
先看看我們寫好的一個登錄功能的接口:

使用變量
現(xiàn)在登錄的賬號和密碼參數(shù)都是寫死的,也就是不過我們執(zhí)行多少次,都是拿這個賬號去測試。那么如果想要測試賬號密碼參數(shù)使用其它值有沒有異常怎么辦呢?( 想要每次都手動改的可以跳過這部分 /手動滑稽)這里我們先簡單講一下在?Postman
?中使用如何“變量”,如下圖:

引用一個變量的語法:{{變量名}}, 圖中可以看到,我們將賬戶和密碼字段的參數(shù)值都設置為變量:{{username}} 、{{password}}
?。修改完直接點擊運行?(Send)
?當然是不行的,因為目前這兩個變量還未被賦值,不過我們可以在?Pre-request Script
?面板中進行賦值操作:
Pre-request Script
Pre-request Script
?與?Tests
?類似,區(qū)別在于:Pre-request Script
?中的腳本是在執(zhí)行請求之前運行,而Tests
?中的腳本則是在請求完成之后執(zhí)行。所以,我們可以在?Pre-request Script
?功能區(qū)中用腳本先個上面兩個變量進行賦值,如:
//設置全局變量
postman.setGlobalVariable("username",?"test1");
postman.setGlobalVariable("password",?"123456");
但是用?Pre-request Script
?進行賦值操作仍然不能解決我們的問題,因為按照這種寫法,不論運行多少次其實都還是用固定(寫死)的數(shù)據(jù)進行測試。當然既然是腳本語言,也會有更靈活的用法,這邊先不將。
測試數(shù)據(jù)集
接下來我們講講?Data File
?, 在運行集合前的這個選項就是用來上傳測試數(shù)據(jù)(文件)以賦值給相應變量的。我們先以?CSV
?格式的測試數(shù)據(jù)為例:
????username,password
????test1,123456
????test2,222222
????test3,123456
????test4,444444
數(shù)據(jù)格式類似表格,第一行表示對應的變量名,下面 4 行表示 4 組賬號密碼數(shù)據(jù)(其中兩組為正確數(shù)據(jù)) ,我們保存一份內(nèi)容為上述示例數(shù)據(jù)后綴名為.csv
?的文件后,再次開始測試看看效果,我們選擇運行次數(shù)為 4 (對應 4 組測試數(shù)據(jù))、選擇對應的?CSV
?文件運行后,可以看到我們的結果確實如我們的預期。接口?Request
?運行的結果為兩次成功兩次失敗,也就是每一次運行都賦值了不同的賬號密碼的測試數(shù)據(jù) (在最新的桌面客戶端版本中可以看到每次具體的請求情況,這邊就不再細說了)。
如果使用?Json
?文件的話,那么格式如下:
????[
??????{
????????"username":?"test1",
????????"password":?"123456"
??????},
??????{
????????"username":?"test2",
????????"password":?"222222"
??????},
??????{
????????"username":?"test3",
????????"password":?"123456"
??????},
??????{
????????"username":?"test4",
????????"password":?"444444"
??????}
????]
2.3 定期任務
Postman
?提供了一個?Monitors
?(監(jiān)視器)功能,支持我們提交一個測試任務,按照設置的定時器進行運行,如每小時測試一次,具體操作如下:

請求依賴問題

講完接口結果判斷和集合批量測試后,我們再來看看比較復雜的情況,即依賴請求問題,比如我們的購物下訂單接口要求必須先登錄后才可訪問。但大部分依賴問題其實本質(zhì)上就是一個接口間數(shù)據(jù)傳遞的問題,比如調(diào)用登錄接口后返回一個標識,假設為?token
?,那么我們請求下訂單接口時只要一起攜帶?token
?參數(shù)進行請求即可。所以,問題變?yōu)椋?/p>
保證接口調(diào)用順序
將接口A返回的數(shù)據(jù)傳遞給后續(xù)的接口B、C、D
3.1 接口執(zhí)行順序
首先,說明一下,接下來說的接口都是默認屬于同一個集合?(Collections)
?中的。
還是以我們上文中創(chuàng)建好接口集合為例,如果你有注意我們執(zhí)行批量測試的結果,就會發(fā)現(xiàn)接口的執(zhí)行順序其實就是按照這邊目錄中的順序(從上到下),即:?Request1 -> Request2 -> Request3
。

這邊接口名字可能有點誤導性,所以再強調(diào)一下:按目錄中從上到下的順序執(zhí)行 (與字典排序無關)
所以有了這個默認的執(zhí)行順序后,那么我們便可以把需要優(yōu)先執(zhí)行的接口放前面即可,比如把“登錄接口”放在第一個。
自定義執(zhí)行順序
當然,如果只有默認的一個執(zhí)行順序的話,通常沒法滿足我們復雜的業(yè)務需求,所以?Postman
?為我們提供了一個函數(shù):postman.setNextRequest("填寫你要跳轉的接口名")
?,支持我們跳轉到指定接口繼續(xù)執(zhí)行,舉個例子:
我們在運行完?Request1
?接口成功后,不需要再運行?Request2
?而是直接跳至?Request3
?,那么我可以在?Request1
?接口的?Tests
?功能區(qū)中執(zhí)行跳轉代碼,如:

這里需要注意幾點:
1.?postman.setNextRequest()
?只在運行集合測試的時候生效,也就是說我們單獨運行?(Send)
?接口Request1
?時,函數(shù)是不起作用的。
2. 當我們運行集合測試成功從?Request1 -> Request3
?后,如果?Request3
?后面還有接口,那么后面的接口仍然繼續(xù)按默認順序執(zhí)行,即圖中的接口?Request4
?仍會被執(zhí)行。
3. 指定的跳轉接口必須屬于同一個集合中。
4.?setNextRequest()
?函數(shù)不管在?Tests
?腳本中何處被調(diào)用,它都只在當前腳本最后才被真正執(zhí)行。比如我們將圖中的第二行與第一行互調(diào)后,那么在運行跳轉函數(shù)后第二行代碼仍會被執(zhí)行。
所以,利用?setNextRequest()
?函數(shù),我們便可以按照條件跳過不必要的接口,或者建立我們自己的一個邏輯測試。
3.2 數(shù)據(jù)傳遞
在講數(shù)據(jù)傳遞前,先聊聊?Postman
?中全局變量、環(huán)境切換的使用。
全局變量
全局變量的概念其實我們在上文中講?Pre-request Script
?時有簡單提到,也就是說我們可以通過腳本代碼來設置全局變量,我們可以看看運行上文的腳本后的效果:
我們可以看到運行后,username
?和?password
?兩個變量已經(jīng)被成功保存下來,那么我們在任意接口中便都可以通過變量引用的語法如:{{username}}
?來使用它們。
另外,Postman
?不僅支持代碼設置全局變量的方式,它還支持可視化操作:

進入對應界面后,便可直接進行管理:

多環(huán)境區(qū)分與切換
通常情況下,我們的接口都會分為測試版本和線上版本(或者更多),而他們的區(qū)別可能僅是?ULR
?不同,那么全局變量便不大合適解決這個問題。
參數(shù)的創(chuàng)建
可能你已經(jīng)注意到,上圖中我已經(jīng)建有幾個不同環(huán)境的參數(shù)“集合”了,再看一下:

我在每個環(huán)境中都創(chuàng)建了一個?host
?參數(shù),如:

當然,我們的環(huán)境參數(shù)也可以通過腳本的方式來進行設置,函數(shù)為:
//注意,該參數(shù)只添加到你當前選擇的環(huán)境的“參數(shù)集”中
postman.setEnvironmentVariable("variable_key",?"variable_value");
使用與切換
環(huán)境“參數(shù)集” 中的參數(shù)使用方式和全局變量一致,如圖中?{{host}}
?,不同環(huán)境的切換見下圖:

3.3 解決依賴問題
掌握以上的預備知識后,我們開始看看如何用?Postman
?解決存在依賴關系的接口測試。
假設場景
我們的接口?Request1
?為登錄接口,登錄成功將會返回一個?access_token
?字段作為標識(已實現(xiàn))。那么假設接口?Request3
?為一個下訂單的接口,需要攜帶登錄返回的?access_token
?才能正常訪問。
思路
1. 保證?Request1
?在?Request3
?之前被運行
2. 將?Request1
?返回的?access_token
?的值添加到環(huán)境變量"參數(shù)集"中。
3.?Request3
?在請求時引用?access_token
?的值
將返回值存在 “全局變量” 或者 “環(huán)境變量” 中,視具體業(yè)務情況而定,該例中?
access_token
?的值是與環(huán)境有關的,所以這里選擇使用環(huán)境變量集存儲。
Postman 中的操作
1. 我們目錄中已保證?Request1
?接口優(yōu)先執(zhí)行
2.?Request1
?中?Tests
?的代碼情況:
if(responseCode.code?===?200?&&?responseBody.has("access_token")){
????//如果?code?為?200,?并且返回的數(shù)據(jù)中存在?access_token?關鍵字,則認為登錄成功
????tests["login"]?=?true;
????//將返回的內(nèi)容轉為?json?格式,并且取到?access_token?內(nèi)容,添加到環(huán)境變量中
????var?jsonData?=?JSON.parse(responseBody);
????//access_token的取值方式視具體的?json?數(shù)據(jù)結構而定
????postman.setEnvironmentVariable("token",jsonData.result.access_token);??
????//跳轉到?Request3?接口
????postman.setNextRequest("Request3")
}else{
????tests["login"]?=?false;
????//登錄失敗,可以選擇跳轉到對應失敗后的處理接口進行測試
????//postman.setNextRequest("Other?Request")
}
3. 在接口?Request3
?中使用變量?token
?:

>?我這邊是將?`token`?放在頭部信息中,?具體使用方式時接口參數(shù)規(guī)則而定。
運行并查看結果
運行集合測試,可以看到我們結果符合我們的預期,Request1
?和?Request3
?通過測試,Request2
?被跳過,Request4
?仍被執(zhí)行。Done…