天天看點

測試學習6Api測試API自動化測試架構的前世今生微服務模式下API測試

Api測試

API測試基本步驟

  • 主要包括三大步驟

準備測試資料(可選)

通過API測試工具,發起對被測API的request

驗證傳回結果的response

對于API測試往往采用API測試工具,如指令行工具cURL,圖形界面工具Postman,API性能測試Jmeter

基于Spring Boot建構API

功能簡單,基于提供的ID值建立一個Account對象,并傳回這個新建立Account對象

  • 使用cURL指令行工具進行測試,調用示例

curl -i -H “Accept: application/json” -X GET “http://127.0.0.1:8080/account/ID008”

這行指令中參數含義

第一個參數“-i”,說明需要顯示response的header資訊;
第二個參數“-H”,用于設定request中的header;
第三個參數“-X”,用于指定執行的方法,這裡使用了GET方法,其他常見的方法還有POST、PUT和DELETE等,如果不指定“-X”,那麼預設的方法就是GET。
最後“ http://127.0.0.1:8080/account/ID008 ”,指明了被測API的endpoint以及具體的ID值是“ID008”。
           
  • 當使用cURL進行測試時,常用參數還有兩個
  • “-d”:用于設定http參數,http參數可以直接加在URL的query string,也可以用“-d”帶入參數。參數之間可以用“&”串接,或使用多個“-d”。
  • “-b”:當需要傳遞cookie時,用于指定cookie檔案的路徑。

常用的cURL指令及使用場景

Session場景

-如果後端工程師使用session記錄使用者登入資訊,那麼後端通常會傳遞一個session ID給前端,之後前端在發給後端的requests中header中需要設定此Session ID,後端從此ID識别出前端是哪個具體的session

  • 此時指令行:curl -i -H “sessionid:XXXXXXXXXX” -X GET “http://XXX/api/demoAPI”

    集體指令

// 将cookie儲存為檔案
curl -i -X POST -d username=robin -d password=password123 -c ~/cookie.txt "http://XXX/auth"
// 載入cookie到request中
curl -i -H "Accept:application/json" -X GET -b ~/cookie.txt "http://XXX/api/demoAPI"
           
  • cURL隻能發起API調用,本身不具備結果驗證能力(驗證由人完成),嚴格意義上,cURL不算測試工具

使用圖形界面工具postman進行測試

應用廣泛,常被用于web service API測試

第一步,發起API調用

  • 需要選擇postman的’request’子產品,進入相應的界面後,輸入URL,選擇GET方法,點選Send發起API調用
  • 傳回的response預設以JSON檔案形式顯示在下面的body中

第二步,添加結果驗證

  • 假設測試過程中有以下四個驗證點
請求的傳回狀态碼(Status Code)應該是200;
請求的響應時間應該小于200 ms;
請求傳回的response header中應該包含“Content-Type”參數;
請求傳回的response body中,“type”的值應該是“friends”;
           
  • 如何驗證,需要打開Tests界面,在SNIPPETS依次點選
Status code: Code is 200”
“Response time is less than 200 ms”
“Response headers:Content-Type header check”
“Response body: JSON value check”
           
  • 點選後,Tests會自動生成驗證碼,接着隻要按照具體的測試要求,對生成的代碼進行小修改就可以了
  • 在這裡,隻需要修改驗證的JSON鍵值對即可,修改完成後點選SEND發起測試

儲存測試用例

  • Collection是用來儲存測試request的一個集合,Collection還可以建立目錄結構以友善進一步的分類和管理
  • 點選Save AS按鈕,在彈出的對話框中可以建立Collection,并且可以命名測試request并将其儲存到Collection中,以後再要使用這個測試request時,直接在Collection中打開它
  • 先在Collection中建立一個,再點選Save AS選擇對應的Collection即可

基于Postman的測試代碼自動生成

  • 如果希望将測試requests作為回歸測試用例內建到CI/CD的流程中
  • 1,将postman中的測試requests用自動化的方式直接轉換成API測試代碼
  • 目前Postman已經支援這個功能,可以将儲存的request自動轉換成常見測試架構支援的代碼
  • 點選code按鈕進入代碼生成界面
  • 2,利用Newman工具直接執行Postman的Collection
  • 首先需要将postman中的collection導出為JSON檔案,然後執行下面指令
  • newman run examples/sample-collection.json;

如何應對複雜場景的API測試

測試場景1:被測業務由多個API調用協作完成

  • 很對情況下,一個單一的前端操作可能會觸發後端一系列的API調用,由于前端測試不确定性/性能測試要求,必須直接從後端通過模拟API順序用來模拟測試過程
  • 涉及一系列API調用,會經常存在後一個API需要使用前一個API傳回結果,以及需要根據前一個API結果決定後面應該調用哪個API情況
  • 可以通過代碼将上個API調用傳回結果的某個值傳遞給下一個API等
  • 如何才能高效擷取單個前端曹祖偶所觸發的API調用序列
  • 解決這個問題的核心思路是:通過網絡監控手段,捕獲單個前端操作所觸發的API調用序列,可以通過Fiddler網絡抓包工具擷取調用序列,可以考慮基于使用者行為日志,通過大資料手段擷取序列

測試場景2,API測試過程中第三方依賴

  • API之間是存在依賴關系的,如果A内部調用了B,當B不可用時,那麼A就會受影響
  • 在單體架構下,通常隻會在涉及第三方API內建的場景中才會遇到這個問題,但是在微服務架構下,API間互相耦合的依賴問題就會非常嚴重
  • 這個問題的核心思路是,啟用Mock Server來代替真實的API
  • Mock可以簡單想象成為了輔助測試而使用的真實api替代品,如果Python一般使用requests架構

測試場景3,異步API的測試

  • 異步API是指,調用後會立即傳回,但是實際任務并沒有真正完成,而是需要稍後去查詢或者回調的API
  • 對異步API測試主要分為兩個部分:一是,測試異步調用是否成功,二是,測試異步調用的業務邏輯處理是否正确
  • 測試是否成功,主要檢查傳回值和背景工作線程是否被建立兩個方面就可以
  • 測試業務邏輯比較複雜,因為異步API通常發生在比較慢的操作上,如資料庫IO,消息對壘IO,此時測試需要去驗證資料庫中值,消息對壘中值,這需要測試代碼有通路和操作消息隊列的能力
  • 在實際工程項目中,這些能力一般會在測試架構級别提供,也就是說要求API測試架構包含對應的工具類去通路和操作資料庫或者消息對壘等

API自動化測試架構的前世今生

  • 了解API測試是如何一步一步發展成今天的樣子,以‘知其是以然’的方式加深對API自動化測試的了解

早期基于postman的API測試

  • 手工操作多,需要解決兩個問題,當需要頻繁大量執行測試用例時,基于界面的API測試顯得有些笨拙;基于界面的測試難以與CI/CD流水線內建
  • 需要一套可以基于指令執行的API測試方案,這樣API測試可以直接通過指令行發起

基于postman和newman的API測試

  • postman+newman+jenkins可以很友善實作API測試與CI/CD流水線的內建,newman是一個指令行工具,可以直接執行postman導出的測試用例
  • 如果涉及連續調用多個API并且有參數傳遞的情況,poatman+newman就不再是理想的方案了

基于代碼的API測試

  • 為了解決上述問題,出現了基于代碼的API測試架構,比較典型的是,基于java的OkHttp和Unirest,基于Python的http.client和Requests,基于NodeJS的Native和Request等
  • 對于大型網際網路企業,一般會自己開發更适合自身業務上下文的API測試架構,這種架構在使用上有很多優點,而且靈活性也很好,主要展現在以下幾個方面:
1,可以靈活支援多個API的順序調用,友善在多個API之間傳遞,即上一個API調用傳回結果中的某個字段值可以作為後續API調用的輸入參數
2,友善在API調用之前或者之後執行額外的任意操作,可以在調用之前執行資料準備操作,可以在調用之後執行現場清理工作
3,可以很友善支援資料驅動測試,就是可以将測試資料和測試代碼分離解耦
4,由于直接采用代碼實作,是以可以更靈活處理驗證斷言(assert)
5,原生支援指令行的測試執行方式,可以友善地和CI/CD工具做內建
           
  • 基于代碼地API測試雖然靈活性好,也可以友善和CI/CD內建,但是引入新的問題
  • 對于單個API測試的場景,工作量相比postman大得多,無法直接寵用postman裡面積累的collection

自動生成API測試代碼

  • 自動生成API測試代碼是指,基于poatman的collection生成基于代碼的API測試用例,直接使用,存在兩個問題
測試中斷言部分不會直接生成代碼,就是測試代碼生成隻支援發起request部分,不會自動生成驗證測試點代碼
測試代碼實作一般會和開發的API測試架構綁定,Postman不支援這類代碼自動生成
           
  • 理想做法是實作一個代碼生成工具,輸入collection中的json檔案,輸出API測試架構的測試代碼,同時把測試的斷言一并轉化為代碼
  • 工具本質就是解析collection json檔案中各個部分,然後根據API架構代碼模闆實作變量替換
首先,根據API架構的代碼結建構立一個帶有變量占位符的模闆檔案
然後,通過json解析程式,按照collection json檔案的格式定義去提取header, method等資訊
最後,用提取的具體值替換之前模闆中的變量占位符
           
  • 有了這個工具後,工作模式可以轉換
對于postman中已經積累的collection,全部由這個工具同一轉換成基于代碼的API測試用例
開發人員繼續使用postman執行基本的測試,并将所有測試用例儲存成collection,後續統一由工具轉換成基于代碼的API測試用例
對于
複雜測試場景,可以組裝由工具轉換得到的API測試用例代碼,完成測試工作
           
  • 實際使用中,測試驗證中的斷言不好處理

Response結果發生變化時自動識别

  • 對于API測試來說,一個很重要的概念就是,後向相容性(釋出的新版本應該能相容老版本API)
  • 後向相容性除了要求API調用參數不能變,還要求不能删減或修改傳回的response字段,因為傳回的response會被下遊的代碼使用
  • 是以在這個基礎下,誕生了’Response結果變化時的自動識别技術’,就是說,即使沒有針對每個字段去做驗證,我們仍然識别出那字段發生可
  • 推薦做法時,在API測試架構建立一個資料庫,一般采用非關系型資料庫,然後用這個資料庫記錄每次調用的requsts和response組合,當下次發送相同request時,API測試架構就會自動和上次的response做差異檢測,對有變化的字段給出警告
  • 可以建白名單,把動态值的字段排除在外(token, session ID, 時間戳等)
  • 可以根據httprunner的yml腳本規則,再加上一些開源元件,做成web頁面進行代理抓包,測試人員無論是從web頁面還是app操作,隻要設定代理過來,就可以看到自己的請求

微服務模式下API測試

  • 微服務架構下,API測試最大的挑戰來自龐大的測試用例數量以及微服務之間的互相耦合

單體架構(Monolithic Architecture)

  • 單體架構是早期的架構模式,将所有的業務場景表示層、業務邏輯層和資料通路層放在同一個工程中,最終經過編譯、打包、部署在伺服器上
  • 單體架構具有釋出簡單、友善調試、架構複雜性低等優點
  • 随着産品承載的流量越來越龐大,問題:
靈活性差:無論是多小的修改,哪怕隻修改了一行代碼,也要打包釋出整個應用,由于所有代碼都放在一起,每次編譯都需要很長時間
可擴充性差:在高并發場景下,無法以子產品為機關靈活擴充容量,不利于應用的橫向擴充
穩定性差:當單體應用中任何個一個子產品有問題,都可能造成應用整體的不可用,缺乏容錯機制
可維護性差:随着業務複雜性提升,代碼複雜性也是直線上升
           
  • 正是一系列問題,催生了微服務架構

微服務架構(Microservice Architecture)

  • 微服務是一種架構風格,在微服務架構下,一個大型複炸軟體系統不再由一個單體組成,而是由一系列互相獨立的微服務組成,其中,各個微服務運作在自己的程序中,開發和部署都沒有依賴
  • 不同服務之間通過一些輕量級互動機制進行通信,如RPC,HTTP等,服務可獨立擴充伸縮,每個服務定義了明确的邊界,隻需要關注并很好的完成任務即可,不同服務可以根據業務需求實作的便利性而采用不同的程式設計語言來實作,由獨立的團隊來維護
  • 微服務架構特點:
每個服務運作在獨立的程序中,開發采用的技術棧也是獨立的
服務間采用輕量級通信機制進行溝通,通常是基于HTTP協定的restful api
每個服務都圍繞具體的業務進行建構,并且能夠被獨立開發、獨立部署、獨立釋出
對運維提出了非常高的要求,促進了CI/CD的發展與落地
           

微服務架構下的測試挑戰

  • 由于微服務架構下,一個應用是由很多互相獨立的微服務組成,每個微服務都會對外暴露接口,同時微服務之間粗壯乃級聯調用關系,也就是說,一個微服務通常還會調用其他微服務
  • 挑戰主要來自兩個方面:過于龐大的測試用例數量;微服務之間的耦合關系

第一,過于龐大的測試用例數量

  • 需要既能保證API品質,又能減少測試用例數量的測試政策–基于消費者契約的API測試
  • 如服務分A,B,C需要測試C。按照測試邏輯需要建構覆寫C的所有測試用例,但是數量太多,發現C的使用者是一定的,即A,B,就變成了測試A,B調用C的所有可能方式
  • 本質上,這樣的用例集合就是C對外提供的服務契約,是以叫做,基于消費者契約的API測試
  • 如何找到A,B對C的所有調用,在邏輯結構上隻要在C前放置一個代理,所有進出C的請求和響應都會經過這個代理,并記錄成json檔案
  • 實際項目中,在微服務架構往往存在一個叫做API Gateway元件,用于記錄所有API之間互相調用關系的日志,可以通過解析API Gateway日志分析得到每個Service的契約

第二,微服務之間的耦合關系

  • 解耦的方式就是實作Mock Service來替代被依賴的真實service,實作這個Mock Service的關鍵點就是要能真實模拟Service的請求和響應
  • 拿到契約後,契約的本質就是請求和響應的組合,具體表現形式往往是json檔案,可以用這個json檔案作為mock Service的依據,就是在收到什麼請求回複什麼響應