用自動測試來確保 API 文件和程式行為保持一致

我們團隊一直用 apiDoc 來產生 API 文件。但隨著數次迭代開發, API 文件已經有部分內容和程式不一致,於是我開始動手整理 API 文件。

更新文件的過程中要一直 trace 許久之前 commit 的 code,這過程不僅繁瑣而且相當惱人。我在整理的過程中一直想:如果在 code commit 時就知道程式行為和文件描述不一致,可以趁著記憶猶新的當下立即處理,這樣就不用定期 review 文件了!


怎麼開始?

我第一個想法就是用自動測試幫我檢查文件是否和程式一致:透過文件去產生測試案例。為此我需要先達成幾個前提:

  1. API 文件:該 API 文件格式必須可以很方便的用程式 parse。
  2. 測試工具:這個工具必須可以把測試案例寫成腳本用 command line 執行,最後產出測試報告。
  3. 預警:當測試失敗時,要知會所有相關人等。
  4. 整合平台:把上述功能整合在一起。

實作工具

接下來就開始實作了!

  1. API 文件

由於團隊內部一直都使用 apiDoc 產 API 文件,而 apiDoc 最後的產出物有一分 JSON 格式的資料,用程式 parse 非常方便,可以直接套用。格式如下:

{
"type": "get",
"url": "/getAccount/:id",
"title": "取得帳號資訊",
"name": "getAccount",
"parameter": {
"fields": {
"Parameter": [
{
"group": "Parameter",
"type": "string",
"optional": false,
"field": "id",
"description": "會員編號"
}
]
},
"examples": [
{
"title": "成功獲取會員資料",
"content": "{\"id\": 100000000000}",
"type": "json"
}
]
},
"success": {
"examples": [
{
"title": "成功獲取會員資料",
"content": "HTTP/1.1 200 OK
{
\"data\":{
\"birthday\": \"1999-11-02\"
\"id\": 100000000000,
\"firstName\": \"姓\",
\"familyName\": \"名\"
},
\"success\": true
}",
"type": "json"
}
]
},
},

2. 測試工具

由於公司的 QA team 是使用 robot framework 進行 web 測試,為了可以無縫將這套機制整合進 QA 的既有系統,我們選擇用 robot framework。

接著我寫了一個腳本將 apiDoc 的產出 json 文件轉換成 robot framework 的測試案例格式如下:

*** test cases ***
| getAccount 成功獲取會員資料
| | ${expect string}= | Set Variable | {"data":{
"birthday": "1999-11-02",
"id": 100000000000,
"firstName": "姓",
"familyName": "名"},
"success": true }
| | ${result}= | get Request | api-url | /getAccount/100000000000 |
| | ${resultJson}= | Set Variable | ${result.json()}
| | Should Be Equal | ${result.status_code} | ${200}
| | ${expect_json}= | Evaluate | json.loads($expect_string) | json
| | Dictionaries Should Be Equal | ${expect_json} | ${resultJson}

這樣就可以用 robot framework 執行測試腳本產報告了!

3. 預警

公司內部使用 Slack 溝通,而且 Slack 對各大 CI/CD 工具支援度都很高,所以這段我直接選用 Slack。

4. 整合平台

公司的 QA team 用 Jenkins 統整所有產品的測試。和測試工具 robot framework 一樣,為了可以無縫整合進 QA 的既有系統,直接使用 Jenkins。


成果

最後的成果如下圖:

每次 commit code 都會觸發 Jenkins 跑測試任務,測試案例由是即時 parse API 文件產生,測試結果會回傳到 GitHub 的 commit status。

若是測試失敗,意味著程式行為和文件有所衝突,則會從 git 記錄找到最後 commit 的開發人員,並在 slack 頻道 tag 該工程師附上 Jenkins 連結, 如此相關人員馬上就會知道有東西壞了:無論是忘記更新文件或者是程式改壞了。