天天看點

使用 Postman 做 API 自動化測試

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

進階點的用法可以使用 Postman 生成各個語言的腳本,還可以抓包,認證,傳輸檔案。

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

Collection

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

  • Collection 對應一個Application,組内各個成員(server, client, QA)共享一個 Collection。可以對整個Collection 添加測試,文檔。 對于一開始未在 postman 組織請求的應用,可以設定 Proxy,跑一遍應用,對應用的所有請求進行抓包。
  • Folder (ItemGroup) 對應一個子產品,或者各層級子路由。如 

    router.use('/users')

     所有的請求都在一個 Folder,可以根據路由互相嵌套 Folder。
  • Request (Item) 對應一個請求,可以添加認證資訊。也可以設定代理,進行抓包。
  • 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,與項目內建在一起,納入版本控制,友善靈活。

《2021測試開發各大機構最新全套教程》:https://pan.baidu.com/s/17jkyGn-Wm-zC6QQLkWjrsw 

  提取碼:o94n 

測試

對于每一個 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 自動生成資料就好了...

測試請求參數

一個請求帶有若幹參數,如 

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 the postman collection runner

內建測試

單個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 https://api.getpostman.com/collections/{{collection_uid}}?apikey={{postman-api-key-here}} --environment https://api.getpostman.com/environments/{{environment_uid}}?apikey={{postman-api-key-here}}      

對比UI自動化測試

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

而API 自動化測試用來測試資料是否正确。而且大部分問題是出在資料問題上,是以 API 自動化測試成本效益比較高一些。

如果對軟體測試、接口測試、自動化測試、面試經驗交流。感興趣可以加軟體測試交流:1085991341,還會有同行一起技術交流。

總結

  1. 如何編寫測試用例
postman 底層使用 

[chai.js]

 的 bdd 文法作為斷言庫,另外加了一些特有的文法。
  1. 如何debug
點選菜單欄 View -> Show Devtools (Show Postman Console) 可以檢視響應,檢查輸出,不過不能打斷點。對于系統的單個請求,可以使用 Proxy 監聽請求進行調試。
  1. 如何使用js第三方庫對請求就行預處理以及後處理

比如: 發送請求時,伺服器端要求時間為 

timestmap(unix)

 的格式,但接口調試時可讀性過弱,是否可以使用 

moment

 轉化時間。 收到響應時,也需要 

moment

 對時間進行解析,獲得更好的展現形式。或者使用 

lodash

 一些函數進行資料的處理。

可以在 Tests 和 Pre-request Script 中編寫腳本對請求以及響應做一些處理。但是不能對資料格式化,比如日期。 建議前後端交流日期時使用 ISO 格式的字元串,前後端都容易解析,并且可讀性強。
  1. 如何管理請求依賴
使用 Environment Variables 可以管理依賴
  1. 如何設定統一的請求參數
目前好像沒什麼辦法
  1. 如何內建到伺服器端項目中
可以使用 npm 包 newman 來內建到項目中

繼續閱讀