還在手工寫介面自動化用例?這種方式可以試試!
- 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即可。
故事的結尾
故事開頭我們已經講過了,這個方案是一個用完即拋的方案。它有自己的一個適用範圍,並不是所有項目都適用的,想要用在常規項目中,一定要能保證每次回放前能恢復原始測試環境。
另外使用這種方法,想要修改個別用例就會比較麻煩;所以錄製的時候可以按相關業務,錄製到一個集合中;修改的時候以一個集合為單位統一重新錄製即可。