使用Postman做API自動化測試

Postman API 自動化測試:

Postman 最基本的功能用來重放請求,並且配合良好的 response 格式化工具。

高級點的用法可以使用 Postman 生成各個語言的腳本,還可以抓包,認證,傳輸文件。

僅僅做到這些還不能夠滿足一個系統的開發,或者說過於瑣碎,你仍需要頻繁地在開發環境,測試環境,生產環境中來回切換。單一的請求也不夠,你需要維護系統所有 API 的請求,並且每個請求還帶有不同的 querystring 和 body。

一、Collection:

對伺服器端的所有請求按功能或者業務模塊進行組織,使用 markdown 對所有請求和示例添加適當的描述,這時候就用到了 Collection。以下是 postman 的一些術語以及組織請求的建議。

詳細參考 Postman SDK Concepts 以及 creating collections

1、Collection

對應一個Application,組內各個成員(server, client, QA)共享一個 Collection。可以對整個 Collection 添加測試,文檔。

對於一開始未在 postman 組織請求的應用,可以設置Proxy,跑一遍應用,對應用的所有請求進行抓包。

2、Folder (ItemGroup)

對應一個模塊,或者各層級子路由。如 router.use(/users) 所有的請求都在一個 Folder,可以根據路由互相嵌套 Folder。

3、Request (Item)

對應一個請求,可以添加認證信息。也可以設置代理,進行抓包。詳見 capturing http requests。

4、Example

對應一個請求不同的參數以及響應,用於Mock Server 以及文檔。

postman 可以根據 Collection 的結構生成文檔與Mock Server。不過都是付費功能,免費版有次數限制。

二、文檔

postman 自動生成文檔有助於團隊協作,解決了手動寫文檔,以及更新不及時的重大bug。

對於 GET 請求,Postman 上可以添加對該欄位的描述,生成文檔。

對於 POST 以及 PUT 請求,如果 Content-Type 是 form-data 或者 x-www-form-urlencoded可以添加描述生成文檔。不過如今傳遞 json 更方便靈活,所以 application/json 也會有很多,而且 json 又是不能添加註釋的。如果需要對 json 添加文檔說明的話,可以添加冗餘欄位 _{key}.comment 標明注釋

{

"id": 128,

"_id.comment": "id",

"page": 10,

"_page.comment": "頁數"

"pageSize": 15,

"_pageSize.comment": "每頁條數"

}

不過這樣冗餘欄位過多,更好的解決方案是在測試中對請求進行 json 校驗,同時充當了一部分文檔的功能。畢竟 json-schema 就是用來描述數據使數據更加可讀。

以上說到請求,對於響應的文檔,可以 json-schema 校驗或者每個欄位的描述,以及更多的測試用例代表更多的細節。

三、Mock

當伺服器端還沒有寫好 API 時,客戶端可以根據 Examples 來生成 Mock Server。

建議客戶端端自己做 Mock,與項目集成在一起,納入版本控制,方便靈活。強烈推薦 json-server,簡單好用。

四、測試

對於每一個 Request 都需要有測試用例。驗證響應是否成功,響應時間是否過長或者響應 json 的數據類型是否正確。

測試可以使用 pm.expect 進行 BDD 測試,風格和 chai 很像,如果熟悉 chai 就很容易上手。

postman 內置了一些第三方庫,如果你更喜歡 chai ,可以直接使用,也可以使用 pm.expect底層使用 chai 實現,與 chai BDD API 一致。

postman 也有一些 http 相關的測試 API,如 status code,header, body,並且也提供了一些 snippets。

// 響應成功

pm.test(Status code is 200, () => {

pm.response.to.have.status(200)

})



// 響應成功 chai.expect

pm.test(Status code is 200, () => {

chai.expect(pm.response).to.have.property(code, 200)

})



// 校驗響應數據

pm.test(Page is 100, () => {

const jsonData = pm.response.json()

chai.expect(jsonData.page).to.eql(100)

})

五、Json Schema

json-schema 可以用來描述 json 信息,使 json 更加易讀,同時也可以用來校驗 json 的合法性。主流語言都有實現 json-schema 的庫。

建議對所有 GET 響應進行 json-schema 校驗,一來校驗數據,二來也可以作為文檔使用,使用 tv4 校驗 json

pm.test("User info", () => {

const jsonData = pm.response.json()

const schema = {

title: UserInfo,

discription: 用戶信息,

type: object,

required: [age, email, name],

properties: {

age: {

description: 年齡,

type: number,

mininum: 0,

},

email: {

description: 郵箱,

type: string

},

name: {

description: 姓名,

type: string

}

}

}

pm.expect(tv4.validate(jsonData, schema)).to.eql(true)

})

同樣對於請求也可以添加 json 校驗,不過更複雜一些,因為 postman 沒有直接給出獲取全部請求參數的api,需要自己解析和計算

// 獲取 application/json 中的數據

const json = JSON.stringify(pm.request.body.raw)

// 獲取 GET query string 的數據

const qs = pm.request.url.query.toObject()

如果 postman 可以根據請求參數的 json-schema 自動生成數據就好了...

參考:

json-schema.org

tv4 Documentaion

chai bdd - API

postman sandbox api reference

六、測試請求參數

一個請求帶有若干參數,如 GET 的 querystring(search) 以及 POST 的 body,不同的參數會有不同的響應。

假設一個請求不同參數返回的 json schema 完全不同,則可以寫成兩個 Request 分開測試。如果返回的 json schema 相同,只是值不同,則需要考慮傳遞了哪些參數,參數是多少。

一個經典的場景,根據 filter 來篩選符合條件的列表。拿用戶列表舉例,偽代碼如下

const url = /api/users

const query = {

name: san,

age: 12,

sex: MALE

}

// 注意query數據需要校驗,防止 SQL 注入

const sql = `select * from users where name = ${query.name} and age = ${query.age} and sex = ${query.sex}`

一個思路是根據請求的參數進行測試,一段重要的 snipet 是在 postman 中獲取 querystring,query 是一種 PropertyList 的數據,定義在 postman-collection - PropertyList。如下

const name = pm.request.url.query.get(name)

const age = pm.request.url.query.get(age)

if (name) {

pm.test(Items should match the name, () => {

const jsonData = pm.response.json()

expect(_.uniq(jsonData.rows.map(row => row.name))).to.eql([name])

})

}

// 冗餘代碼有些多,postman不知道支不支持自建 snipets

if (age) {

pm.test(Items should match the age, () => {

const jsonData = pm.response.json()

expect(_.uniq(jsonData.rows.map(row => row.age))).to.eql([age])

})

}

當然以上 filter 只包含了最簡單的場景,其中只涉及到了相等測試。但是有不等以及包含關係呢。

const query = {

name: san,

age: 12,

sex: MALE

}

const sql = `select * from users where name like ${query.name} and age < ${query.age} and sex = ${query.sex}`

這種請求參數依賴於前後端的協商交流,當然對測試或者一個不知情的開發來說很不友好的。

當然對於後端也是不友好的,因為需要對你傳入的每個 query 來進行處理,而且以後每添加一個篩選欄位,都需要手動改一下。

可以由前端自行決定需要篩選的數據,比如使用類似於 mongo 的檢索語法。

graphql 是相當酷的,值得嘗試一下

const query = {

name: {

$like: san

},

age: {

$lt: 12

},

sex: MALE

}

不過這對於測試的開發能力要求也比較高了,測試人員需要解析參數並且測試介面。

七、測試多次請求

當對一個函數進行單元測試時,需要大量的輸入以及期望輸出,在postman中,可以使用 data 來模擬多次輸入

data 是一種變數,只能在Runner 中使用,有必要對每個 Folder 建立相關的data file,並且加入版本控制。

…………………………using csv and json files in thepostman collection runner……………………………………

blog.getpostman.com/201

八、集成測試

單個API測試通過後,需要把所有請求集成在一起進行測試。這時候出現了兩個問題

1.如何確保API依賴

2.API之間如何傳遞數據

請求在 Collection 的順序就是他們的發起請求的順序,如果需要強制更改順序,可以使用 setNextRuest()

在 postman 中有三種作用域的數據,data,environment,global。在請求中用 {{}} 佔位符替代。

environment 可以用來更改 HOST,避免在 url 中頻繁手動切換本地環境,開發環境和生產環境。另外也可以用來傳遞數據。

一個常見的場景是項目使用 token 來保存登錄信息,每次請求都需要攜帶token。可以在登錄的測試代碼中設置 token 的環境變數

const url = http://{{HOST}}/api/login

pm.test(There is a token, () => {

const jsonData = pm.response.json()

pm.expect(jsonData.token).to.a(string)

pm.environment.set(token, jsonData.token)

})

const urlNext = http://{{HOST}}/api/profile?token={{token}}

九、測試Collection

確保依賴後,可以對 Collection 新建一個 Runner,並且引入一個 data 文件來測試所有的請求。對局部的 Folder 也可以使用 Runner 以及 data 進行測試。

最新版本的 postman 已經可以支持,為每個 Postman 新建變數以及 Test

所有的請求都會有一些共同測試,比如測試介面是否響應成功以及以上提到的測試 filter

pm.test(Response is right, () => {

// status code: 2XX

pm.response.to.be.success

})

pm.test(Filter is matching, () => {

// ...

})

十、持續集成

當可以測試 Collection 後,需要對測試加入版本控制,與項目集成在一起,保留測試記錄,以便準時定位 bug。可以與 postman 的官方工具 newman 集成在一起,但是有一點不方便的是,持續集成僅僅可以保存記錄,並不能還原記錄。

newman run

api.getpostman.com/coll{{collection_uid}}?apikey={{postman-api-key-here}} --environment api.getpostman.com/envi{{environment_uid}}?apikey={{postman-api-key-here}}

十一、對比UI自動化測試

按照我的理解,UI 自動化測試目的是用來測試流程是否通暢,比如登陸,註冊,退出,如果用例沒通過則截屏。但是前端需求的不斷變化,加上現在各種前端框架,導致 selector 不是特別容易獲取到且流程容易更改。

而API 自動化測試用來測試數據是否正確。而且大部分問題是出在數據問題上,所以 API 自動化測試性價比比較高一些。

十二、總結

1.如何編寫測試用例

postman 底層使用 [chai.js](chaijs.com/api/bdd/) 的 bdd 語法作為斷言庫,另外加了一些特有的語法。

2.如何debug

點擊菜單欄 View -> Show Devtools (Show Postman Console) 可以查看響應,檢查輸出,不過不能打斷點。對於系統的單個請求,可以使用 Proxy 監聽請求進行調試。

3.如何使用js第三方庫對請求就行預處理以及後處理

比如:

發送請求時,伺服器端要求時間為 timestmap(unix) 的格式,但介面調試時可讀性過弱,是否可以使用 moment 轉化時間。

收到響應時,也需要 moment 對時間進行解析,獲得更好的展現形式。或者使用 lodash 一些函數進行數據的處理。

可以在 Tests 和 Pre-request Script 中編寫腳本對請求以及響應做一些處理。但是不能對數據格式化,比如日期。

建議前後端交流日期時使用 ISO 格式的字元串,前後端都容易解析,並且可讀性強。

4.如何管理請求依賴

比如:兩個API需要有依賴關係,比如當創建完一個用戶後(註冊),獲取他的個人信息。獲取個人信息就需要依賴創建用戶這個API。

使用 Environment Variables 可以管理依賴

5.如何設置統一的請求參數

比如:

大部分介面都需要統一的 token 參數。

目前好像沒什麼辦法

6.如何集成到伺服器端項目中

如果系統後續版本沒有通過API測試,則保留測試記錄是很重要的,版本控制可以得知該時間段內的代碼變更。以git為例,需要每次提交後運行測試,並保留測試結果。

可以使用 npm 包 newman 來集成到項目中


推薦閱讀:

自動化測試
自動化測試丨如何滿足自動化測試需求?
你們測試用例越來越多,刪不刪?
單元測試之旅:預見優秀之①——優秀基因
DevOps入門教程——Jenkins持續集成篇

TAG:工程學 | 自動化測試 | 自動化 |