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 :P
這里對測試結果中的幾個指標進行說明:
樣本數目 | 總共發送到服務器的請求數。 |
最新樣本 | 代表時間的數字,是服務器響應最后一個請求的時間。 |
吞吐量 | 服務器每分鍾處理的請求數。 |
平均值 | 是總運行時間除以發送到服務器的請求數,即每個請求的平均響應時間。 |
中間值 | 是代表時間的數字,有一半的服務器響應時間低於該值而另一半高於該值。 |
偏離 | 表示服務器響應時間變化、離散程度測量值的大小,即數據的分布。 |
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代碼的效率和性能。當然,工具只能“錦上添花”,最根本的還是需要我們自己可以編寫出高質量的代碼啦 :D