apache jmeter是apache軟件基金會出品的一款用於接口測試,壓力測試的開源軟件,由於其免費開源,插件j自由擴展,跨平臺,所以理論上可以支持所有種類的接口測試。jmeter自身也已經提供了許多優秀的插件,極大地增強了jmeter的能力。
問題引入
jmeter提供了兩種運行模式,一種是GUI模式,一種是CLI模式,這兩種運行模式有各自的場景:
GUI-圖形用戶界面:
顧名思義,用戶可以在任意支持java的操作系統上打開一個jmeter客戶端,因爲GUI模式下提供了可視化的腳本編排工具,因此常用於腳本編排。
CLI:
命令行模式,也叫non-GUI,headless(無頭模式),可以在不啓動jmeter圖形客戶端的情況下發起腳本測試,CLI模式是更常用的jmeter運行模式,因爲不需要啓動圖形客戶端,所以該模式下佔用的資源會更少,是在負載測試和壓力測試中最常用的運行模式。
無論使用jmeter執行何種類型的測試,都離不開腳本的編排,GUI模式下固然可以編排腳本,但是這種方式在面對現在越來越盛行的敏捷開發及devops理念時稍微顯得心有餘而力不足,主要的問題在以下幾個方面:
碎片化嚴重:當新的需求完成或舊的需求發生變更時,需要重新編排測試腳本,腳本很難管理或碎片化非常嚴重。
歷史記錄難以回溯:每次使用jmeter進行性能測試都會生成新的日誌、報告,使用本地文件系統管理這些數據可行,但是想要回溯腳本的整個執行歷史基本上是不可能的。
溝通成本高:針對每一個開發需求的測試及缺陷的管理被強制性隔離,測試人員與開發人員的溝通成本極高,這與敏捷及devops的理念是不符的。
質量管控:產品或項目在發版前的質量控制靠測試人員人工控制,當面對大型的項目中成百上千個測試用例時,靠人工控制產品或項目的質量,困難重重。
沒有針對不同管理人員的報告:測試人員關心用例的成功率、開發經理關心缺陷趨勢、開發者關心缺陷產生的原因、項目經理關心測試覆蓋率……,這些都需要有一套平臺集中管理測試數據才能實現。
基於以上的問題,想要集中管理jmeter腳本相關的測試數據,首先要解決的一大問題就是:脫離jmeter GUI模式,在自己的測試平臺上實現在線編排測試腳本,這將會涉及到jmeter的二次開發。
從目前apache官方放出來的資料來看,只有全部的源代碼、客戶端使用手冊,就連接口文檔都是殘缺不全的,再加上jmeter自身作爲一個平臺,第三方可以通過插件擴展的方式對jmeter進行增強,因此二次開發的難度很高,需要進行技術攻關。
上圖來源於jmeter的官方網站,可以從其導航菜單看出,僅提供了用戶使用手冊、java DOC
問題探究
通過研究jmeter軟件架構和腳本的結構,發現其軟件核心在ApacheJmeter_core.jar, ApacheJmeter_components.jar這兩個jar包上,它們分別的功能如下:
- ApacheJmeter_core.jar,定義Jmeter所有的核心接口、工具類、報表生成邏輯、通用的斷言、執行相關邏輯……
- ApacheJmeter_components.jar,定義通用GUI組件、菜單控制、GUI界面的渲染、表單的生成邏輯……
而jmeter的腳本則是在統一的規範下生成的,如下圖:
圖中是測試計劃的插件標籤腳本,它包含了guiclass和testclass兩個核心的通用屬性,外加其它不同數據類型的字段,其它的插件也是同樣的格式,它們分別的含義如下:
1.標籤上屬性均爲通用屬性,這些屬性是由ApacheJmeter_core.jar中的AbstractJMeterGuiComponent類定義,其中:
- guiclass表示jmeter在GUI模式渲染該插件時使用哪個類;
- testclass表示jmeter在執行腳本到該插件時使用哪個類;
- testname是插件的自定義名稱;
- enabled表示是否啓用該插件,只有enabled爲true的插件都會被執行。
2. 標籤下的子標籤表示該插件的自定義屬性,由插件的開發廠商根據插件的功能自己確定。
綜合以上的分析結果,可以發現,想要在測試平臺上集成jmeter腳本編排,核心的便是研究每一個插件的guiclass,確定屬性的定義及值的約束規則。確定完以上的技術要點就完成了二次開發技術攻關,剩下的只有對需要二次開發插件的表單字段的默認值確定、約束規則確認。
技術攻關完成了,下面來到下一個主題,如何構造一個jmeter腳本?觀察下面的jmeter腳本代碼:
在前面的插件標籤腳本中有講到,所有的jmeter插件都是由通用屬性加上自定義屬性表示,在通用屬性中定義的guiclass會定義插件的字段,但是jmeter的字段是和gui插件深度綁定的,如果爲了編排插件引入guiclass類的初始化,會額外增加大量的內存開銷,這裏就需要做一些變動,當確認完guiclass類中的插件字段後,渲染腳本的時候直接繞開它,使用自定義的方式來組裝插件字段。
Jmeter擁有大量的插件,包括官方的和第三方的,數量衆多,插件在腳本中的位置也不是固定不變的,這帶來了兩個問題:
- 插件太多,必須要有一個統一的構建方式構建插件,以不變應萬變;
- 編排的腳本中插件的層級無法事先確定。
針對第一個問題,輪到設計模式出場,23種設計模式中的建造者模式正好可以適應這種需要以不變應萬變的場景。
註釋:建造者模式(Builder Pattern)又叫生成器模式,其定義爲:將一個複雜對象的構造與它的表示分離,使同樣的構建過程可以創建不同的表示,這樣的設計模式被稱爲建造者模式。它是將一個複雜的對象分解爲多個簡單的對象,然後一步一步構建而成。它將變與不變相分離,即產品的組成部分是不變的,但每一部分是可以靈活選擇的。
針對第二個問題,雖然腳本中插件的層級無法事先確認,但是在jmeter客戶端可以確定任何一個插件的下一級插件有哪些,這個時候輪到遞歸出場。
解決方案示例
綜合以上所有的問題分析,做完了所有的前置準備工作後,可以開始插件的組裝邏輯的編寫,下面以TestPlan插件爲例:
遞歸遍歷插件表單封裝,通過事先確定的jmeter插件層級並封裝在插件json中,遍歷時可以很容易控制任務層級的插件字段的封裝。
建造者構造插件字段,通過建造者模式提供統一的抽象,屏蔽jmeter底層,只需要調用對應插件的Builder就可以構建相應的插件腳本。
總結
通過以上關於jmeter二次開發整個研究流程,可以將技術性問題的處理流程總結如下:
- 描述清楚需求,給出初步的技術方案;
- 針對技術方案做分析,找出可能存在的技術難點;
- 針對每一個技術難點,從不同的角度分析並找到問題的解決方案;
- 針對每一個解決方案做技術論證,論證方案可行性,確定最終的解決方案;
- 綜合各個解決方案,進行綜合論證,確定整個大的方案是可行的;
- 實施方案,通過單元測試驗證所有的邏輯是符合需求。