本篇開始,將陸續介紹基於Java+HttpClient+TestNG的接口自動化測試框架。(這里需要閱讀的童鞋們有Java的編碼知識及HttpClient和TestNG的使用經驗。)
首先,我們需要討論一下,什么是接口測試?為什么要做接口測試?以及我們這個框架解決的問題是什么。
什么是接口測試?首先需要說明一下什么是接口。按照百度的定義,接口------外部系統與系統之間以及內部各個子系統之間的交互點。這么說有點抽象,簡單來說,如果我要在一個網頁中顯示一些數據/文字什么的,我需要有數據來源,碰巧這些數據來源是需要經過邏輯計算的,又碰巧這些數據來源不是來自同一個服務器。那么,如果我直接把這些邏輯和請求都寫在頁面上顯然是不合適的。這時,我們需要去請求一個接口,這個接口就是頁面顯示和后台服務之間的交互點。接口測試就是測試這個交互點的功能是否正常,我所需要的數據是否按既定的邏輯進行返回。從這個意義上來說,接口測試非常簡單,我們只需要考慮各種輸入條件下,會產生相應的什么結果,是最為簡單的黑盒測試!
那么為什么要做接口測試呢?無他,總體來說就是成本低,效果好,速度快。
在前端的童鞋還沒有完成UI頁面之前,傳統的測試是不太可能進行的。而接口測試不需要UI界面,直接通過接口去驗證后台邏輯。而且,如果有人通過抓包,直接跳過前端的校驗,去進入后端的程序。也是一件很危險的事情。因此,接口測試可以盡可能早的開展。越早介入測試,發現的問題解決起來的成本是越低的。在傳統的測試中,開發沒有將完整產品提交給測試時,測試這邊是無法工作的。而在現在流行的敏捷開發中,開發可以寫完一個接口就進行一輪接口測試的回歸,以最小的代價快速保證質量。
接口測試性價比很高,很多公司也比較喜歡進行接口測試。那么當我們做接口測試時,到底需要做哪些方面的工作呢?
- 獲取需求文檔和接口文檔 --------> 實際有可能沒有,有可能不全。
- 通過對需求文檔分析出接口的業務邏輯要求以及業務邊界 -------->對測試的業務場景進行構建
- 通過對接口文檔分析出接口的技術指標(接口地址、請求方式、入參、出參)-------->實際測試的之前必須搞清楚要訪問接口的信息。
- 接口測試用例設計(着重於接口測試數據准備)-------->業務數據的准備尤為重要。
- 使用接口測試工具進行接口測試 --------> 可以使用Jmeter,Postman等軟件,也可以使用自動化測試框架
- 接口缺陷管理與跟蹤 -------->生成測試的log與報告
- 接口自動化持續集成 -------->用於Jenkins平台
在這里,有一個誤區,很多人認為會使用接口測試工具就是會接口測試。其實接口測試遠遠不止是工具的使用,Jmeter也好,Postman也好,這些工具都是我們在進行接口測試過程中能夠更方便的進行測試,而工具僅僅是工具,真正核心部分還是接口測試用例設計以及測試思維。
既然已經有了接口測試的軟件,也能一定程序上實現接口測試的自動化操作。為什么我們還要費勁周折的去寫接口自動化測試框架呢?說實話,我一開始也不是很明白。直到后來,我遇到了這樣一個接口,
這個接口的訪問需要輸入一個sign作為參數。而這個sign的獲取方式如下:
int A 為當前系統的Unix時間戳。(即1970年1月1日到現在有多少秒),String B為當前用戶所對應的secret數據庫id(一個32位字符串),String C為當前的appkey(可以通過另外一個接口獲得),
將int A轉為16進制,然后變成字符串,與B及C拼接成字符串D,然后對字符串D取MD5的值,作為sign。
說實話,這個我不知道用Jmeter或者Postman怎么做。尤其是int A每一秒都不一樣。在這種情況下,自己寫個工具來解決,是不是方便很多呢?
針對一些使用工具進行接口測試的痛點,就說說我們這個接口自動化測試框架能夠解決哪些問題。
- 采用數據驅動方式來解決大量功能重復性接口的測試。
- 針對返回JSON字符串,采用JSONPath的模式來精准判定JSON的內容。
- 可以生成比較直觀的報告。
當然,也可以集成很多小工具。比如上面提到的計算MD5的值。
先開個頭,想想一個接口的請求及返回是由哪些構成的呢?
請求的有:url,訪問方法,請求頭,body,參數等,返回的有json字符串,狀態等。
我們可以根據接口的訪問和返回的內容,做成一個Bean,來記錄請求和返回及判定的數據,而這些數據都記錄在Excel中。
現在做成Excel的基礎類:
package apiTest.bean; public class baseBean { private String excelName; private String sheetName;
public String getSheetName() { return sheetName; } public void setSheetName(String sheetName) { this.sheetName = sheetName; } public String getExcelName() { return excelName; } public void setExcelName(String excelName) { this.excelName = excelName; } }
然后,我們的api請求及返回繼承這個基礎類。
package apiTest.bean; public class apiDataBean extends baseBean { private boolean run; //是否運行 private String desc; // 接口描述 private String method;//訪問方法 private String url; //接口訪問url //header的情況相對復雜,可以設置公共header,也可以針對個別請求來設定訪問的header。 private String header; private String body;//接口請求時的body private boolean contains; //是否對返回的json字符串中作包含判定(針對接口返回內容較多,不好具體制定路徑的情況) private int status; //返回狀態 private String verify;//判定內容 private String save; //需要保存的內容 private String param; //接口發送需要的參數 private int sleep; //暫停時間 public boolean isRun() { return run; } public void setRun(boolean run) { this.run = run; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getHeader() { return header; } public void setHeader(String header) { this.header = header; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } public boolean isContains() { return contains; } public void setContains(boolean contains) { this.contains = contains; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public String getVerify() { return verify; } public void setVerify(String verify) { this.verify = verify; } public String getSave() { return save; } public void setSave(String save) { this.save = save; } public String getParam() { return param; } public void setParam(String param) { this.param = param; } public int getSleep() { return sleep; } public void setSleep(int sleep) { this.sleep = sleep; } @Override public String toString() { // TODO Auto-generated method stub return String.format("desc:%s,method:%s,url:%s,param:%s", this.desc, this.method, this.url, this.body); } }
好的,這樣我們就對接口及返回數據制作了一個類,這個類就是接口測試的數據模型。
開篇先寫道這里。之后我們來討論配置的讀取和設定。
