利用Postman實現簡單的自動化測試
1. 關於tests[]
斷言
對於系統整套介面的測試最好是建立系統相關的Collection,便於以後測試,測試指令碼採用的是JavaScript語法編寫,指令碼主要寫的位置在Pre-request Script
和Tests
兩個欄目中,Pre-request Script
主要用於在請求傳送之前執行,Tests
用於請求傳送之後執行,在Postman中也提供了一些簡單的斷言,比如:
// 判斷返回的狀態碼是否為200
tests["Status code is 200"] = responseCode.code === 200;
// 判斷返回的內容中是否存在指定關鍵字
tests["Body matches string" ] = responseBody.has("關鍵字");
// 判斷返回內容是否跟預期完全相等。
tests["Body is correct"] = responseBody === "預期的內容";
// responseBody為字串型別,支援轉為 Json 格式
var jsonData = JSON.parse(responseBody);
tests["Your test name"] = jsonData.value === 100;
// 判斷請求時長是否小於200ms ,具體時長按情況自定義
tests["Response time is less than 200ms"] = responseTime < 200;
上述test
命令的語法基本是:
test["類似於函式名字"] = 一個判斷條件
函式名字可以隨緣嘛,只要見名知意就行了(比如上面判斷狀態碼是否為200就是Status code is 200
),判斷條件可以是各種形式,比如數值、字串的相等可以用===
、響應體中包含關鍵字可以用responseBody.has("關鍵字")
函式、以及>
、<
等等,只要最後返回的是一個布林值即可,為true
即表示通過,false
為失敗,tests
的直接賦值作用比較侷限,如果在指令碼中進行一些其他非同步操作,則需要用到pm.test
了,比如:
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
一般使用test
賦值和pm.test/pm.expect
已經可以滿足基本的測試需求了。也可以在測試請求拿到結果後再根據這些結果傳送新的新的請求,然後新增斷言,如:
// 將JSON響應體轉成json
let responseJSON = JSON.parse(responseBody)
// 獲取關注的第一個使用者,並請求他的使用者資訊
pm.sendRequest(responseJSON[0].url, function (err, response) {
let responseJSON = response.json()
pm.test('has email', function () {
pm.expect(responseJSON.email).is.be.true // 如果使用者email不存在,斷言則會失敗
})
});
如果我們有一些動態介面要進行測試,可以嘗試這種寫法,一級介面返回List
,二級介面根據List
的ID進行獲取對應資訊。
2. 關於變數global
和environment
Postman提供了兩種變數:一個是global
,一個environment
。其中global
可以像下面這樣操作:
pm.globals.set("variable_key", "variable_value") // set variable
pm.globals.get("variable_key") // get variable
pm.globals.unset("variable_key") // remove variable
上述是使用指令碼的方式設定global
變數,這一點在Account中很實用,使用者在登入後可以直接利用pm.globals.set("variable_key", "variable_value")
的方式將cookie
設定到全域性變數中,這樣後續的操作就可以利用這個cookie
獲取到使用者的狀態是登入的狀態。變數設定完,可以在測試的URL中使用{{..}}
雙括號的形式包裹global
變數來使用。
environment
變數的權重要比global
變數更高一些,針對某些環境來進行設定,操作方式和上述類似(也是用雙花括號的形式包裹變數即可),在發起請求(一個或多個)時,可以勾選對應的環境來使用不同的變數,environment
變數可以使用的位置如下:
URL
URL params
Header values
form-data/url-encoded values
Raw body content
Helper fields
在對大量API測試時,使用environment
設定domain
和context-path
是比較推薦的,比如:
// 在環境管理中配置一個domain變數,值為https://api.github.com
domain: https://api.github.com
// 使用雙括號的形式在URL中引用環境變數
{{domain}}/res1
{{domain}}/res2
具體設定環境變數時可以這麼幹:
postman.setEnvironmentVariable("variable_key","variable_value");
postman內部也提供了三種隨機數的生成方式(未測試通過):
{{$guid}}
:新增一個V4風格GUID;{{$timestamp}}
:將當前的時間戳,精確到秒;{{$randomInt}}
:新增0和1000之間的隨機整數;
3. Run Collection
在自動化測試過程中,通常是通過 Run Collection 的方式一次跑大量的API,Collection 建好後直接點選左上方的Runner
按鈕,即可進入介面,對其中的幾個引數做一些說面:
上述介面的引數依據實際情況進行設定即可。
關於介面的執行順序
預設情況下,介面是按照我們編寫的順序執行的,即介面在前面的就先執行,在後面就後執行,如果想手動指定介面的執行順序,可以在介面的Tests
一欄中使用setNextRequest
函式指定下一個要執行的介面,如:
# 當前介面執行完畢後就會繼續執行Request2介面,而不管位置上在它下一個的介面
postman.setNextRequest("Request2");
4. 變數解析
在通過postman中在RequestBody中放List
,遇到JSON解析問題,原來是要往裡面塞一個List<Long> feedbackIds
,後來在postman中直接這麼放的:
{
"feedbackIds":[
1194812025388864,
1195607949901632
]
}
然後出現下面的解析異常:
"exepct '[', but {, pos 1, json : {\n\t\"feedbackIds\":[\n\t\t1194812025388864,\n\t\t1195607949901632\n\t]\n}"
在JSON解析的時候,後端是要的一個List
,而前端傳過來的確實一個物件(這一塊感覺說不太清楚,應該都有這種感覺),最終直接通過最簡單的方式傳入得以解決(傳入[xx, xx, ..]
的形式),直接將傳入的資料改寫為:
[
1194812025388864,
1195607949901632
]
很多情況下,API返會給前端的資料都是封裝成下面的JSON格式:
{
"code": string,
"message": string,
"data": T
}
在此時斷言responseBody中的具體JSON內容時,比如返回的內容為:
{
"code": "invitee.not.reach",
"message": "The Invitee not reach."
}
那在斷言的時候先轉JSON再取其中的內容進行判斷:
// 轉成json
var jsonData = JSON.parse(responseBody);
// 取json中具體需要斷言的key做判斷
tests["check qualification"] = jsonData.message === "The Invitee not reach."
除此外,postman還可以斷言 response 的頭部資訊,如:
// 斷言響應頭中是否有Content-Type
tests["Content-Type is present"] = responseHeaders.hasOwnProperty("Content-Type");
// 獲取Content-Type的值
var ct = postman.getResponseHeader("Content-Type");
// 判斷Content-Type的型別是否相符
tests["Content-Type is image/gif;charset=UTF-8"] = postman.getResponseHeader("Content-Type") === "image/gif;charset=UTF-8";
// 判斷Cookie的值,cookie一般都是很多cookie一起,中間以分號間隔
var cookied = postman.getResponseHeader("set-cookie");
// 將多個cookie字串切割為一個個單個的cookie
cookies = cookied.split(";");
// 將該介面寫入的cookie中的最後一個設定為postman全域性環境變數,從而影響後面介面的測試
postman.setEnvironmentVariable("Cookie",cookies[0]);
// 如果知道了cookie的名字,想直接取這個cookie的值
var cuk_yk = postman.getResponseCookie("cuk_yk").value;
【注意】
上述流程中在獲取整個cookie時使用的是postman.getResponseHeader("set-cookie")
這個函式,如果這個介面在後臺邏輯內部有設定cookie的行為,第一次使用postman測試該介面時postman.getResponseHeader("set-cookie")
函式可以獲取到設定的cookie的頭欄位set-cookie
,但是一旦這個執行過該介面後cookie被寫進去了,沒有清cookie執行第二次的時候,postman發現該cookie存在就不會去設定對應的cookie,介面響應體中也不會出現set-cookie
頭欄位,所以最終獲取的cookied
為null
,從而也導致cookied.split(";")
函數出現TypeError: Cannot read property 'split' of undefined
,因為獲取的cookied
變數為null
,沒法呼叫該函式,很多人會使用(cookied || "").split(";")
方式處理來避免這個錯誤,其中(cookied || "")
其實類似於三目運算的過程,如果cookied
不為null
結果就為cookied
,否則結果為一個空串。
5. 具體操作
這裡只記錄我遇到的一些不太注意的東西,常規操作自行百度,有下面一些:
關於環境變數
在建立環境時,我以為只有在Run Collection時才能使用,然後為了在測試單個介面時,在每個介面的Pre-requestScript中都用指令碼寫了domain和context-path:
pm.environment.set("domain","http://www.xxxx.com");
pm.environment.set("contextpath","/api");
但實際根本不需要,在配置好環境變數後,在下圖的紅色框中選用即可:
關於除錯或postman輸出、列印
postman在寫測試指令碼的時候也是可以進行簡單列印除錯的,只是之前沒有用過,但不是常規意義上打端點進行debug,而是利用console.log()
函式將變數進行輸出,關鍵是輸出你最起碼有個類似於控制檯的地兒啊,這玩意找了大半天,調出postman控制檯的操作流程如下:頂部選單欄View–> Show Postman Console,或者直接快捷鍵Ctrl+Alt+C,這樣在指令碼使用console.log()
就可以將需要檢視的變數顯示出來了。