HTTP API 自動化測試從手工到平臺的演變

不管是 Web 系統,還是移動 APP,前後端邏輯的分離設計已經是常態化,相互之間通過 API 呼叫進行資料互動。在基於 API 約定的開發模式下,如何加速請求 / 響應的 API 測試,讓研發人員及早參與到除錯中來呢?既然 API 是基於約定開發,為何不按照這個規範編寫測試用例,直接進入待測試狀態,使用自動化的方式來推進研發過程的質量改進呢?遵循:測試 -> 重構 -> 測試 -> 重構,這樣的閉環,過程產出的質量會更加可控,在重構的同時進行快速的功能迴歸驗證,大大提高效率。下面主要講解基於 HTTP 協議的 API 測試,從手工測試到平臺的演變過程。
手工測試帶來的困惑
測試團隊採用《敏捷腦圖用例實踐之路》的方式編寫測試用例:

圖 -1- 分計費單元查詢頻寬
優點:
-
要點清晰簡潔展現
-
所有測試故事點經過用例評審,產生質量高,研發參與感強;
-
版本同步保持一份
API 測試腦圖帶來的問題:
-
腦圖用例對測試人員的素質要求相當高
-
完善的腦圖用例編寫,需要有資深的測試人員,對業務精通、對測試技能精通,很強的思維能力;如果研發人員僅僅參考這個腦圖用例進行測試,往往很多時候需要花費大量的溝通時間,其中有很多測試 API 的過程、措施,在腦圖裡面沒有具體體現,造成一些資訊丟失。
-
重複執行不變的是規則,變的只是引數,要消滅重複部分
-
還可以深度優化腦圖用例,API 介面規範,再怎麼天馬行空,也得有個度,應當把重複思考的部分交給工具去做,需要發揮創造力、值得關注部分,交給人工完成;按照這個測試流程,,測試人員編寫完用例,去驗證 API 介面,如果失敗了,打回給研發人員重新修改,但是下一次研發人員提交測試,測試人員又得重新驗證一遍,這一遍中實際沒有多少有價值的思考,是重複工作,要去挖掘測試價值。另外,如果測試人員請假了,那是不是測試就需要延期了呢?消除等待、消除單點作業,改變是唯一出路,嘗試過如下方式:

圖 -2-Chrome DHC 元件
組員通過使用 Chrome DHC(是一款使用 chrome 模擬 REST 客戶端向伺服器傳送測試資料的谷歌瀏覽器外掛),進行 API 自動化測試,用例檔案儲存到本地並且同步到 svn,簡單粗暴解決重複請求問題,注意強調的是解決重複請求,並沒有包括引數和結果的自動化驗證的過程,還是需要人工參與,至少前進了一步,當然我們也解決了單點問題,其他組員可以更新用例本地執行,還差引數校驗,資料校驗等等一堆關鍵業務點要用自動化去突破。
俗話說:術業有專攻,DHC 只是玩玩而已,並不擅長做那麼多活,也做不好,更期望的是平臺化。
平臺雛形:沒有經驗,多麼痛的領悟
經歷了手工測試的繁瑣操作,丟棄了簡單的 DHC,決定另尋新路,API 測試最簡單的場景請求引數組合產生各類別的測試用例。思路很簡單,做一個 WEB 平臺,登記 API 介面,填寫請求引數,對響應結果進行校驗,初期進行了技術選型,使用 Django 做 Python Web 開發,後臺指令碼執行使用開源框架 RobotFramework,RF 優點如下:
-
是一個通用的關鍵詞驅動自動測試框架;
-
易於使用的表格資料展現形式,採用關鍵字驅動的測試方法,使用在測試庫中實現的關鍵詞來在測試中執行程式。
-
是靈活和可擴充套件的,適合用於測試使用者介面;
在這個平臺中,RobotFramework 主要用於後臺執行 Robot 關鍵字指令碼,而關鍵字指令碼,是平臺通過讀取 YAML 檔案生成,該檔案是通過笛卡爾乘積產生的用例,工作原理如圖所示:

圖 -3- 工作原理
那話說回來,YAML 幹什麼呢?為什麼不是 XML 呢?
-
YAML 的可讀性好
-
YAML 和指令碼語言的互動性好
-
YAML 使用實現語言的資料型別
-
YAML 有一個一致的資訊模型
-
YAML 易於實現
聽起來 YAML 試圖用一種比 XML 更敏捷的方式,來完成 XML 所完成的任務。下面通過一段實際例子說明配置生成的 YAML 程式碼段:
主介面配置介面:

圖 -4- 介面配置頁面
設定 API 引數:

圖 -5- 設定 API 引數
配置檔案 byChannelsDaily.yaml(列舉一個引數示例):
- byChannelsDaily:# 介面名稱 method: get# 與伺服器互動的方法 format: json#API 資料格式 url: /reportdata/flux/byChannelsDaily#API 的 URL,與奇台配置檔案裡面的 host 變數組成整個 URL 的前半部分。 url_path: url_params:#URL 引數部分,固定寫法。 username:#API 的引數名。 required: true# 該引數是否必須(true/false)。 value: chinacache# 該引數的值。如此值是從另一個介面獲取的,可在 from_api 設定,此處可不填。如果值是 Boolean,必須加雙引號。 type: string# 該引數值的型別。 len: 10# 該引數值的長度。 max: -100# 該引數值的最大值。-100 相當於忽略此引數 min: -100# 該引數值的最小值。-100 相當於忽略此引數 from_api:# 如引數的值是從另一個介面、global.yaml 中獲取的,請設定 from_api,如 global jsonpath:# 可通過 jsonpath 來指定取值範圍,如 $.version[2:4] range: response:# 期望結果 verification: success: []#success 是一個 list, 它的元素也是 list,success[0] = [ RF 關鍵字 ,驗證欄位,正則匹配] failure: [] error_msg: []# 錯誤資訊集合</pre>
測試報告:

圖 -6-rf 測試報告
按照這個思路做下來,得到什麼收益呢?

自動化
說到這裡,其實,真沒有帶來多少收益,思路對了,但是方向有偏差了,主要體現在:
- 使用了笛卡爾乘積來生成不同引數的測試用例,發現一堆的測試用例生成檔案是 M 的單位,而且也給測試伺服器帶來效能問題,數量 4980 箇中佔 95% 的用例都是沒有實際意義的,對伺服器頻繁請求造成壓力;

圖 -7- 龐大的測試用例檔案
- 通過 WEB 配置將 YAML 檔案轉為 robot 可以識別的,這種做法坑太深、維護難,引數越多, 檔案越臃腫,可讀性差;
- 後來嘗試將笛卡爾乘積換成全對偶組合演算法,效果改進顯著,無效用例數明顯下降,有效用例數顯著提升;
敗了,就是敗了,沒什麼好找藉口,關鍵問題是:
- 有效的測試用例佔比例很低,無效的佔了大部分;
- 沒有化繁為簡,前端隱藏了配置,複雜的配置還是需要在後端處理;
- 沒有實際測試參與動腦過程,測試人員不會窮舉,會根據業務編寫實際用例;
- 平臺易用性很重要:需要測試人員直接在上面編寫,合理的邏輯步驟,有利於引導測試參與;
重構:發現測試的價值
回到起點,測試要解決什麼問題,為什麼要做 API 自動化測試平臺?做這個平臺,不是為了滿足老闆的提倡全民自動化的口號,也不是為了浮誇的 KPI,更不是宣傳自動化可以解決一切問題,發現所有 bug。叔本華說過一句話:由於頻繁地重複,許多起初在我們看來重要的事情逐漸變得毫無價值。如果 API 測試僅僅依靠純手工的執行,很快將會面臨瓶頸,因為每一個功能幾乎都不能是第一次提交測試後就測試通過的,所以就需要反覆 bug 修復、驗證,以及迴歸的過程。另外,很多的 API 測試工作手工做起來非常的繁瑣,甚至不便,比如針對介面協議的驗證、針對返回資料格式的驗證,這些都依賴於測試自動化的開展。因此,真正的目的是解放測試人員重複的手工生產力,加速回歸測試效率,同時讓研發人員在開發過程及早參與測試(自測、冒煙測試),驅動編碼質量的提升。
回顧以往,重新梳理頭緒,更加清晰的展現:

圖 -8-HTTP API 自動化測試圖解
-
HTTP API 傳統手工測試
-
重複請求引數基礎校驗、正確引數查詢返回資料校驗,測試工程師沒有新的創造價值,不斷重複工作,甚至可能壓縮其中的測試環節,勉強交付;
-
HTTP API 自動化測試
-
重複步驟(請求介面是否有效、引數校驗可以作為冒煙測試,研發參與自測)用自動化解決,關鍵業務步驟資料對比人工參與和 schema 自動化校驗;
如果對軟體測試、介面測試、自動化測試、效能測試、LR指令碼開發、面試經驗交流。感興趣可以175317069,群內會有不定期的發放免費的資料連結,這些資料都是從各個技術網站蒐集、整理出來的,如果你有好的學習資料可以私聊發我,我會註明出處之後分享給大家。
最大的收益,重複步驟自動化後,不管是研發人員自測,還是執行功能迴歸測試,成本可以很快收回(前提是你這個專案週期長,構建頻繁;如果僅僅是跑幾個月的專案,真沒那個必要湊熱鬧去自動化,當然有平臺的另當別論),測試的關注點會落實到更加關鍵的業務環節去;
總體規劃如下:
[

圖 -9-HTTP API 重構規劃
-
技術選型
由於原來的測試平臺使用 Python 編寫,為了保持風格一致,從介面錄入到檔案生成處理依然採用 Python、Django,去掉了全對偶組合演算法,改為根據測試人員思維去產生用例;去掉了後臺 RobotFramework 框架,採用 Python 的 HTTP 類庫封裝請求。
-
HTTP API 專案管理 Web 前臺
使用 Python+Django+SQL/">MySQL 進行開發,分為專案首頁、專案配置、API 配置、全域性配置四大部分

圖 -10- 管理 Web
- 專案首頁
介紹:列出 API 規範、API 測試用例、定時任務數量,以及某段時間內的測試結果趨勢圖形。

圖 -11- 專案首頁
-
專案配置
重點介紹:全域性變數、常用方法、驗證器。
全域性變數
設計思路:在 API 測試過程中,可以切換生產、測試環境進行對比校驗,如果寫兩套測試用例是冗餘,全域性變數功能,是一種在執行測試用例時動態改變用例屬性的方法。
作用範圍:當前專案內
使用方法:{變數名}
能在以下測試用例屬性中使用:URL、請求頭、請求引數

圖 -12- 全域性變數配置頁
在 API 用例庫的 URL 可以直接填寫:{host}/reportdata/monitor/getChannelIDsByUserName;當執行測試用例的時候,可以選擇不同的引數套件,後臺程式碼執行會直接替換,這樣子可以分別快速驗證生產環境和測試環境的 API 介面執行結果的差異。

圖 -13- 用例執行頁
常用方法
√ 設計思路:常用方法是一個 Python 函式,對入參進行處理並且返回結果,例如:
gen_md5 作用是生成 MD5,對應程式碼直接填寫:
import hashlib def gen_md5(raw_str): m = hashlib.md5() m.update(raw_str) md5_str = m.hexdigest() return md5_str
√ 應用場景:
在 API 請求中,有些引數例如 pass 需要加密處理,可以通過引入 [常用方法] 來解決。
在引數 pass 的值中直接填寫:
{{get_apipwd("{123456}","ChinaCache")}}</pre>

圖 -15- 介面配置頁
驗證器
√ 設計思路
驗證器是一個 Python 函式,如果函式返回 True,則測試通過;返回 False,則測試失敗。平臺預設提供一個預設驗證器。
預設驗證器是驗證期望結果與實際結果(response body)是否完全一致。如果結果不一致則判斷為失敗,預設驗證器只適用於靜態的響應結果對比。
自義定驗證器,如果預設驗證器不能滿足某些特殊的測試需求,使用者可以在“專案配置 - 驗證器”中新增自定義的驗證器。
√ 應用場景:在 API 測試的返回結果中,可以新增自定義驗證器對資料進行校驗,判斷測試是否通過。

圖 -17- 測試用例驗證展示頁
-
API 配置
重點介紹:通用響應配置、API 依賴庫、API 用例庫、定時任務、測試報告
通用響應配置

圖 -18- 通用響應配置列表頁
√ 設計思路
在合理的 API 設計中,存在通用的錯誤響應碼,[使用者名稱錯誤,返回期望響應內容],如果所有 API 的響應結果中都需要重複寫是相當繁瑣的,作為共同配置呼叫即可。

√ 應用場景
查詢介面遇到使用者名稱密碼為空,可以自定義寫返回內容,以及選擇 [通用響應配置] 下的相關錯誤型別,例如:使用者名稱密碼為空 (計費單元),自動填充期望的返回值:
<BillingIDs> <Result>fail</Result> <DetailInfo>invalid userName or password</DetailInfo> </BillingIDs>

圖 -19- 期望返回值校驗頁
API 依賴庫
√ 設計思路 & 應用場景
API-A 的引數 r_id 依賴與 API-B 返回結果的某個引數(多個引數同樣道理),這裡登記 API-B,並且提取返回引數。除了特有的變數提取器,基本資訊與請求,與後面提到的 API 介面一致的
填寫方式 :

圖 -20- 變數提取器展示頁
該介面返回資料如下;
{ "r_id": "567bbc3f2b8a683f7e2e9436" }
通過 [變數提取器],可以獲取 r_id 的值,以供依賴 API-A 作為引數使用。

圖 -21- 用例中引數包含 r_id 變數展示頁
其中請求引數的獲取如下:

圖 -22- 請求引數變數提取設定
測試結果:
1- 顯示依賴介面;2- 顯示為需要測試的介面,依賴介面返回的 r_id 會傳入作為測試介面的引數;

圖 -23- 測試結果中展示執行時變數提取結果
- API 用例庫

圖 -24- 用例庫設計腦圖
如果對軟體測試、介面測試、自動化測試、效能測試、LR指令碼開發、面試經驗交流。感興趣可以175317069,群內會有不定期的發放免費的資料連結,這些資料都是從各個技術網站蒐集、整理出來的,如果你有好的學習資料可以私聊發我,我會註明出處之後分享給大家。
√ 設計思路
通過自助配置:請求頭、請求引數,響應頭、響應結果校驗,來聚合測試人員日常思考產生的測試用例。
√ 應用場景
支援 HTTP1.1 協議的 7 種請求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE 和 TARCE。最常用的方法是 GET 和 POST:
-
支援 query(問號後)帶引數、path 的 GET|POST 請求
Query: http://192.168.1.11/internal/refresh?username=ChinaCache&password=123456
Path: http://192.168.1.11/internal/refresh/username/password
-
POST 請求支援 application/json、text/xml
示例如下:
請求頭設定:Content-Type:application/json 請求體設定:儲存為 JSON 格式 { "username": "ChinaCache", "password": "123456", "task": { "dirs": [如果對軟體測試、介面測試、自動化測試、效能測試、LR指令碼開發、 ""面試經驗交流。感興趣可以175317069,群內會有不定期的發放免費 ],的資料連結,這些資料都是從各個技術網站蒐集、整理出來的,如果 "callback": {你有好的學習資料可以私聊發我,我會註明出處之後分享給大家。 "url": "", "email": [] }, "urls": [ "http://www.chinacache.com/news/test.html" ] } }
結果如下:

圖 -25-body 引數展示頁
-
支援返回結果的 schema 驗證
在返回大量資料的場景下,把資料格式的正確性交給程式去判斷,通過之後進行人工干預的資料對比,假如返回幾百 K 的資料,你不知道格式是否正確,就開始去做資料對比,這個方向是不對的。
{ "r_id": "567cfce22b8a683f802e944b" } Schema 驗證如下: { "$schema": "http://json-schema.org/draft-04/schema#", "required": [ "r_id" ], "type": "object", "id": "http://jsonschema.net", "properties": { "r_id": { "type": "string", "id": "http://jsonschema.net/r_id" } } }
-
定時任務
√ 設計思路 & 應用場景
定時任務是在計劃好的時間點自動執行指定的測試用例。一個專案支援多個定時任務,如果同一時間點有多個測試任務,將依次執行。定時任務有兩種型別:定時、迴圈(間隔:秒,
分鐘,小時,天,周)。通過定時任務,可以做到晚上執行,早上檢視結果報告分析。

圖 -26- 新增定時任務
-
測試報告 & 郵件通知
√ 設計思路 & 應用場景
每次執行測試用例(包括手動執行和定時任務)之後,都會生成一份測試報告。
報告會詳細列出每個介面的基本資訊(名稱,請求方法,驗證器等),請求資訊(URL 和 body 引數),響應資訊包括 headers, body, schema, content type, status code 5 部分的測試結果,每一部分都有實際結果、期望結果(失敗時顯示)以及 DIFF 對比(失敗時顯示),當在
執行測試時出現錯誤,也會把錯誤資訊顯示出來 。

圖 -27- 測試報告列表頁

圖 -28- 郵件通知
API 實戰:324 個用例(包括 GET|POST 請求,引數有加密、依賴場景,返回結果有簡單驗證資料、錯誤碼驗證、schema 驗證),執行耗時:8min,猜想下,如果人工去跑,需要多久呢?
如果對軟體測試、介面測試、自動化測試、效能測試、LR指令碼開發、面試經驗交流。感興趣可以175317069,群內會有不定期的發放免費的資料連結,這些資料都是從各個技術網站蒐集、整理出來的,如果你有好的學習資料可以私聊發我,我會註明出處之後分享給大家。
提速:研發測試流程改進

圖 -29- 使用 HTTP API 平臺改進 API 研發測試過程
-
改進前:傳統手工測試
測試用例掌握在測試人員手裡,研發人員無法執行,修復 bug 之後,只能等待測試人員驗證,交付過程繁瑣、效率低;
-
改進後:HTTP API 自動化測試
研發、測試協作同步,研發人員可以及早通過平臺執行用例,驗證功能可用性、正確性,測試人員可以釋放部分勞動力,重點關注業務資料正確性;修復 bug 之後,研發人員無需等待,可以自助配置用例執行、檢視結果,驅動過程質量的提升,同時做到夜間構建、郵件通知,工作時間 review、bug fix。
-
問題:何時收回投入成本?
API 專案週期不超過半年的,不建議做自動化,有自動化平臺基礎的另當別論,因為在最初 API 測試用例編寫需要投入大量的時間;這種投入,只有不斷進行迴歸驗證、多次執行,成本才可以回收,往後都是收益,這個道理淺顯易懂。
總結
“由於頻繁地重複,許多起初在我們看來重要的事情逐漸變得毫無價值”,在提測過程有個重要環節:冒煙測試,但是頻繁的去做的話,就是重複性的工作了。
那 HTTP API 介面測試痛點是什麼?研發人員提測之後,需要等待測試人員進行驗證;測試人員發現 bug,需要等待研發人員 bug fix;這裡就產生大量的等待成本(當然,測試人員可以切換到其他專案中去,但是這種上下文的切換成本很高)。通過 HTTP API 自動化測試平臺,研發人員在提測之前,首先進行一輪冒煙測試,根據自動化測試用例檢查結果,提升提測之前的功能質量;一旦提測之後,測試人員的關注重點落到返回結果對比上,這種研發測試過程的效率會得到很大的提升,或許有人要問,到底提升多少呢?這個每個團隊的痛點不同,研發、測試人員磨合程度不同,不能一概而論,大膽邁出一步去嘗試,就會發現價值;當然,往深處去想,下一步可以接入效能的自動化測試,喝杯咖啡的時間,等到自動化執行結果報告產出,是有可能的場景。