還在手工寫介面自動化用例?這種方式可以試試!

  • 2019 年 10 月 8 日
  • 筆記

故事的前奏

測試技術發展到今天,如果你還不會一些自動化技能,不會介面自動化方法,不會寫一個兩個框架,出去都不好意思跟人打招呼!

現階段寫介面自動化用例就跟以前寫手工用例一樣太習以為常了。那麼有沒有更加偷懶的方法,連介面自動化用例都省的寫了呢?答案今天就揭曉!

好吧,我承認已經編不下去了!開始正經拿個小板凳來認真介紹了。這個故事還要從前陣子的一個項目講起…

當時所在項目的「尿性」就是每次大版本上線,介面都可能是一次版本更新(用完即拋);如果按照正常思路去寫介面用例來回歸,可能用例還沒有寫完,項目就已經上線了。

但另一方面,考慮到之前該項目出現過介面類的BUG;所以不敢怠慢,即使在時間非常緊的情況下,還是希望能夠覆蓋到介面測試,盡最大可能的增加測試覆蓋度。

所以最後就整出了一個同樣「尿性」的介面自動化用例生成方案 — 錄製+回放驗證。每次項目錄製一次,用完即拋,再來項目再錄,用完再拋。

故事的GC

同樣是錄製,為了表現的更「騷」。我們也調研了多種方式:

•普通HTTP代理方式(mitmproxy、miniproxy、anyproxy)•基於HOST的代理方式(HProxy)•瀏覽器插件的方式(Chrome、FF)•TCPdump的方式(組裝HTTP協議,不是人乾的事情)

這幾種方式,理論上都是可以完成HTTP協議的錄製,並把請求和響應內容保存到DB,共日後來進行回放和驗證。同時它們也是有各自特點的:

•普通HTTP代理,不能錄製伺服器之間的請求(比如:服務A訪問服務B)•基於HOST代理,配置方式不夠靈活,會影響系統全局的HOST•瀏覽器插件,同樣只能錄製瀏覽器的請求•TCPdump方式,組裝太麻煩,不能跨平台

經過一番激烈的內心鬥爭之後,最後還是覺得怎麼簡單怎麼來,選擇了支援插件開發的普通HTTP代理 — mitmproxy。官方地址:https://www.mitmproxy.org/

這個代理是使用python開發的,所以天然支援python來開發插件,這也是我選擇它的原因。並且它的插件開發不要太簡單,只要編寫一個常規的python文件即可。

在正式使用它之前,需要進行基礎庫的安裝。windows的需要下載exe,linux下則可以直接通過pip install mitmproxy來安裝。下面就是官網的一個插件樣例:

# anatomy.py  from mitmproxy import ctx    class Counter:      def __init__(self):          self.num = 0        def request(self, flow):          self.num = self.num + 1          ctx.log.info("We've seen %d flows" % self.num)    addons = [      Counter()  ]

這裡定義了一個類並實現了一個request方法,最後把這個類註冊到addons變數即可。這個插件用來記錄一共有多少個request請求經過了代理。可以通過以下命令啟動代理:

mitmdump -s ./anatomy.py -p 8181

這裡引用了anatomy.py插件文件,並指定了監聽埠為8181,不指定埠則默認會監聽8080埠。啟動成功之後,只要配置瀏覽器代理指向本地的8181埠即可,之後隨便訪問一個在線網頁,你就會看到列印請求數的日誌。

獲取請求對象

前面樣例只是簡單的記錄了請求數量,而如果想要錄製介面自動化用例的話,則需要分別錄製請求內容和響應內容。這裡我們先看下如果獲取請求內容。

# anatomy.py  from mitmproxy import ctx    class Counter:      def __init__(self):          pass        def request(self, flow):          request = flow.request          data = {              "url": request.url,              "method": request.method,              "headers": request.headers,              "text": request.text,,              "content": request.content,          }          ctx.log.info(data)    addons = [      Counter()  ]

重新啟動執行命令,就會在命令行列印出每個請求的相關資訊。

獲取響應對象

有了請求資訊,還缺少響應資訊。獲取的方式也類似,只要定義一個response方法即可。

# anatomy.py  from mitmproxy import ctx    class Counter:      def __init__(self):          pass        def response(self, flow):          response = flow.response          data = {              "status_code": response.status_code,              "reason": response.reason,              "headers": response.headers,              "text": response.text,              "content": response.content          }          ctx.log.info(data)    addons = [      Counter()  ]

重新啟動執行命令,就會在命令行列印出每個請求對應的響應資訊。

過濾指定URL

默認情況下,插件會接收到經過代理的全量請求對象和響應對象。但實際情況我們不希望錄製非介面的請求,比如:靜態資源。這時就可以通過訂製代理過濾規則的方式很容易的實現了。

# anatomy.py  from mitmproxy import ctx    class Counter:      def __init__(self):          self.filter = flowfilter.parse(ctx.options.dumper_filter)        def request(self, flow):          if flowfilter.match(self.filter, flow):  # 是否匹配規則成功              ctx.log.info(flow.request.url)    addons = [      Counter()  ]

通過如下命令在重新啟動腳本:

mitmdump -s ./anatomy.py -k -p 8181 ~u '^https://www.testqa.cn/static/.*'

此時再訪問網頁如果經過代理的請求,不是以https://www.testqa.cn/static/開頭的URL,則不會被列印出來,只有匹配這個正則的URL才會被列印。

介面用例錄製架構圖

基本的思路已經有了,這裡再給一個完整的錄製+回放的架構圖,剩下的就等著你開幹了!如果你想要獲取完整的程式碼,那麼請關注TestQA公眾號並回復mitmproxy即可。

故事的結尾

故事開頭我們已經講過了,這個方案是一個用完即拋的方案。它有自己的一個適用範圍,並不是所有項目都適用的,想要用在常規項目中,一定要能保證每次回放前能恢復原始測試環境。

另外使用這種方法,想要修改個別用例就會比較麻煩;所以錄製的時候可以按相關業務,錄製到一個集合中;修改的時候以一個集合為單位統一重新錄製即可。