JMeter是Apache組織的開放原始碼項目,它是功能和效能測試的工具,100%的用java實現,最新的版本是2.9,大家可以到官網下載原始碼和查看相關文檔。之前本科的時候,SQA課程作業中我們組使用過2.4版本,這次更新了2.9感覺最直觀的就是介面上有了小的更改,增加了清除、啟動等按鈕。
關於使用JMeter進行JDBC資料庫測試、HTTP請求介面測試、結合Badboy錄製功能進行網站效能測試等內容,網上的資料比較豐富,這裡就暫時不做介紹了。更實用和靈活的情境,是實用我們自己編寫的jar包進行測試,這也就是“Java請求”方式的測試。這裡主要記錄一下我在學習這種測試方式時遇到的一些問題,和總體流程,算作一個記錄和小總結。
1. JMeter安裝
準確的來說,我認為JMeter是不需要安裝的,下載好JMeter Binary版本後,在本地解壓縮,進入bin檔案夾,執行ApacheJMeter.jar檔案即可。這裡提供一個觀望的2.9版本的下載連結,時間久了可能會失效,這個時候可以進入Apache JMeter項目首頁再選擇download頁面。
開啟JMeter程式後,我們可以看到JMeter的主介面,是的這個樣子(2.9版本)。
2. 使用JMeter建立測試計劃
如果我們希望實用JMeter進行效能測試,則首先需要建立一個測試計劃,我們可以對測試計劃進行儲存,這樣當我們下一次需要再次執行這個測試的時候,只需要開啟已儲存的測試計劃檔案(.jmx檔案)就可以執行了,無需再次建立。
1)點擊“測試計劃”,在右側輸入框中可以修改測試計劃的名稱,並添加註釋,這裡我偷個懶就不改了,使用預設的。
2)為測試計劃添加一組Threads,選擇線程組。這組Threads就相當於是一組使用者,每個顯示代表一個使用者執行相關操作。
3) 編輯線程組屬性。設定響應內容,比較重要的是線程數、ramp-up period和迴圈次數。這裡設定線程數為1、ramp-up period為1和迴圈次數1,即線程組中只有1個線程,這個線程在計劃啟動後1秒就開始執行,只執行1次。
圖上的ramp-up period解釋不正確,這個屬性工作表示每個使用者(線程)啟動的遲延時間。例如,如果你輸入Ramp-Up Period 為5秒,JMeter將會在五秒結束前完成啟動所有的使用者。所以,如果你有五個使用者並且Ramp-Up Period為5秒,那麼開始使用者的延遲就是1秒。(5個使用者/5秒=1使用者每秒)。如果你設定的Ramp-Up Period為0,則JMeter將會立即啟動你所有的使用者。
如果勾選了“調度器”,則可以定時啟動線程。
4)為線程組添加Sampler取樣器,取樣器表明這組線程執行測試的類型,即發送請求的類型、怎樣發送請求的。我們這裡選擇“Java請求”,表明這組線程是通過某個Java類發送請求的。
4)編輯“Java請求”屬性。這個大家可以發現已經有了Launcher類,和userName、password、authUrl的值了,這是因為:1. 我之前寫了滿足一定要求的代碼,打了jar包,放入了JMeter的lib/ext檔案夾下了,所以可以看到Launcher;2. 我在Launcher類中的getDefaultParameters方法中添加了預設的userName、password、authUrl值。這裡的“滿足一定要求”請繼續參閱下文。
5)為Java請求添加監聽器,選擇“彙總報表”和“圖形結果”,這樣在啟動測試後,我們就可以獲得測試結果的資料,分別以報表和圖形的結果展示。
6)點擊啟動(功能表列中的綠色三角形按鈕)。測試完成可以看到測試結果。為了結果好看一點,我把線程數改成了10,迴圈改成了100
這裡對測試結果中的幾個指標進行說明:
圖形結果
| 樣本數目 |
總共發送到伺服器的請求數。 |
| 最新樣本 |
代表時間的數字,是伺服器響應最後一個請求的時間。 |
| 輸送量 |
伺服器每分鐘處理的請求數。 |
| 平均值 |
是總已耗用時間除以發送到伺服器的請求數,即每個請求的平均回應時間。 |
| 中間值 |
是代表時間的數字,有一半的伺服器回應時間低於該值而另一半高於該值。 |
| 偏離 |
表示伺服器回應時間變化、離散程度測量值的大小,即資料的分布。 |
彙總報表
| 90%line |
90%的回應時間都比這個時間小 |
| Min |
代表時間的數字,是伺服器響應的最短時間。 |
| Max |
代表時間的數字,是伺服器響應的最長時間。 |
| Error% |
請求的錯誤百分比。 |
| KB/sec |
是每秒鐘請求的位元組數。 |
3. 實現“Java請求”代碼
針對"Java請求"類型的測試,需要基於JMeter測試架構編寫測試案例。
1)建立一個普通的Java工程
2)添加JMeter的包引用,這些包位於 JMeter安裝目錄/lib/ext下,一般只需要ApacheJMeter_core.jar和ApacheJMeter_java.jar這兩個。
3)建立一個Java Class,如下例中的“Launcher”,並繼承“AbstractJavaSamplerClient”。AbstractJavaSamplerClient中預設實現了四個可以覆蓋的方法,分別是“getDefaultParameters”,“setupTest”,“runTest”和“teardownTest”方法。
- getDefaultParameters 方法主要用於設定傳入介面的參數;
- setupTest方法為初始化方法,用於初始化效能測試時的每個線程;
- runTest方法為效能測試時的線程運行體;
- teardownTest方法為測試結束方法,用於結束效能測試中的每個線程。
package cn.edu.zju.swift.test;import org.apache.jmeter.config.Arguments;import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;import org.apache.jmeter.samplers.SampleResult;import cn.edu.zju.swift.JtangSwiftClient;import cn.edu.zju.swift.model.result.AccountResult;public class Launcher extends AbstractJavaSamplerClient{ private JtangSwiftClient client; @Override /** * JMeter介面中展示出此方法所設定的預設參數。 * @return */ public Arguments getDefaultParameters() { Arguments args = new Arguments(); args.addArgument("authUrl", "http://192.168.3.51:8080/auth/v1.0"); args.addArgument("userName", "test:tester"); args.addArgument("password", "testing"); return args; } /** * 執行runTest()方法前會調用此方法,可放一些初始化代碼 */ @Override public void setupTest(JavaSamplerContext context) { // 建立SwiftClient this.client = new JtangSwiftClient(15000, 15000, 8192, true, false); } /** * 執行runTest()方法後會調用此方法,可放一些資源釋放代碼 */ @Override public void teardownTest(JavaSamplerContext context) { // 關閉串連 this.client.close(); } @Override /** * 效能測試時的線程運行體,執行的業務方法放在這裡。 */ public SampleResult runTest(JavaSamplerContext context) { // 建立SampleResult對象,用於記錄執行結果的狀態,並返回 SampleResult sampleResult = new SampleResult(); // 擷取JMeter中輸入的使用者參數 String authUrl = context.getParameter("authUrl"); String userName = context.getParameter("userName"); String password = context.getParameter("password"); // 開始 sampleResult.sampleStart(); AccountResult accountResult = client.auth(authUrl, userName, password); // 暫停 // sampleResult.samplePause(); // 重啟 // sampleResult.sampleResume(); // 結束 sampleResult.sampleEnd(); sampleResult.setSuccessful(accountResult.isSuccess()); // 返回 return sampleResult; }}
4)代碼編寫完畢後,把上面的例子打包(使用eclipse右鍵項目 -> export -> jar,即可)。然後把產生的"swift-random-action-test.jar"檔案拷貝到JMeter的安裝目錄lib\ext下,就可以在上述“2. 使用JMeter建立測試計劃”的4)Java請求編輯頁面的下拉式清單中看到Launcher類了。
這裡有兩點需要注意:
1. 如果你的jar依賴了其他第三方jar,需要將其一起放到lib/ext下,否則會出現ClassNotFound錯誤,這個問題也是困擾了我好久的 T^T;
2. 如果在將jar放入lib/ext後,你還是無法找到你編寫的類,且此時你是開著JMeter的,則需要重啟一下JMeter。
以上就是使用JMeter的Java請求方式進行一個測試計劃構建的全過程了,都是比較基礎的方法,如果需要什麼額外的功能還可以慢慢學習。雖然自己也有寫多線程並發的用戶端測試代碼,並自己收集response time等,計算TPS,但顯然使用JMeter的方式更加方便,因為你只需要按照單線程的方式去實現你的測試業務,也無需添加各種埋點收集資料。
綜上,感覺JMeter還是很強大的,最近打算多學習一點,對以後寫代碼,自我測試效能也是很有協助的,再配合jProfiler的使用,可以很好的保證Java代碼的效率和效能。當然,工具只能“錦上添花”,最根本的還是需要我們自己可以編寫出高品質的代碼啦