BeanShell是最早進的JMeter內置組件之一。JMeter具備豐富的內置插件,可知足性能測試的許多需求。例如,在編寫一些複雜的測試時,您可能須要一些額外的腳本。在這種狀況下,值得使用Beanshell。在這篇文章中,咱們將討論使用JMeter Beanshell和常見用例測試複雜邏輯。Beanshell具備運行Java代碼的功能,而且能夠訪問JMeter API和在JMeter類路徑中加載的外部類。html
JMeter具備如下啓用Beanshell的組件:java
如下是向Beanshell公開的JMeter API類。若是查看Beanshell的底部,您將看到爲腳本定義的變量列表。web
您能夠在Beanshell中訪問
SampleResult類的成員變量和方法。shell
例如,您能夠分別使用setThreadName()
和getThreadName()
方法設置和獲取線程名稱。apache
此類容許您手動設置響應代碼。在某些狀況下,您可能須要根據從服務器得到的響應來設置響應代碼。
這是一個用例示例:api
if(condition){ ResponseCode =「200」; } else { ResponseCode =「500」; }
此類容許您手動設置響應消息。示例用例與for的用例相同ResponseCode
。服務器
IsSuccess
是Boolean
反映採樣器是否成功的反映。若是設置爲true,則認爲採樣器已「經過」。不然,它將被標記爲「失敗」。app
if(condition){ IsSuccess = true; } else { IsSuccess = false; }
ctx
是暴露給BeanShell的最強大的變量。它表明
JMeterContext類,它自己就是JMeter。它提供對底層JMeter引擎,採樣器及其結果以及變量/屬性的讀/寫訪問。ide
如下代碼演示了ctx變量的用法:函數
log.info(「Current Sampler class is:」+ ctx.getCurrentSampler()); log.info(「JMeter Engine類是:」+ ctx.getEngine()); log.info(「上一個響應消息是:」+ ctx.getPreviousResult()。getResponseMessage()); log.info(「上一個響應代碼是:」+ ctx.getPreviousResult()。getResponseCode()); log.info(「Previous Response URL is:」+ ctx.getPreviousResult()。getURL()); log.info(「Previous Response Time is:」+ ctx.getPreviousResult()。getTime()); log.info(「Previous Domain is:」+ ctx.getPreviousSampler()。getDomain()); log.info(「Previous Protocol is:」+ ctx.getPreviousSampler()。getProtocol()); log.info(「Previous Port is:」+ ctx.getPreviousSampler()。getPort()); log.info(「Previous Method is:」+ ctx.getPreviousSampler()。getMethod()); log.info(「Thread Name is:」+ ctx.getThread()。getThreadName()); log.info(「Thread Start Time is:」+ ctx.getThread()。getStartTime()); log.info(「Thread End Time is:」+ ctx.getThread()。getEndTime()); log.info(「在錯誤時啓動下一個線程循環:」+ ctx.getThreadGroup()。getOnErrorStartNextLoop()); log.info(「Stop Test on Error:」+ ctx.getThreadGroup()。getOnErrorStopTest());
另外一個用例是,若是要將全部斷言錯誤寫入HTML文件,以即可以查看哪一個斷言不起做用。您能夠ctx
在Beanshell斷言中使用變量來遍歷當前上下文中的全部採樣器,並將失敗寫入html文件中。
添加Beanshell斷言並複製如下代碼以將全部斷言寫入html文件:
import org.apache.jmeter.services.FileServer; f = new FileOutputStream(「C:\\ apache-jmeter-4.0 \\ bin \\ result.html」,true); pt = new PrintStream(f); pt.println( 「<HTML> <BODY>」); for(a:SampleResult.getAssertionResults()){ if(a.isError()|| a.isFailure()){ log.error(「URL:」+ ctx.getCurrentSampler()。toString()); log.error(Thread.currentThread()。getName()+「:」+ SampleLabel +「:響應失敗:」+ new String((byte [])ResponseData)); pt.println(「URL:」+ ctx.getCurrentSampler()。toString()); pt.println(Thread.currentThread()。getName()+「:」+ SampleLabel +「:響應斷言失敗:」+ new String((byte [])ResponseData)); pt.println( 「</ BODY> </ HTML>」); pt.close(); f.close(); }
它是
JMeterVariables類的一個實例,提供對當前變量的讀/寫訪問,可以枚舉/更改現有變量,建立新變量以及獲取嵌套屬性。全部JMeter變量都是Java字符串。若是您須要將其餘內容添加到JMeter變量中,則須要先將其強制轉換爲字符串。如下代碼段演示瞭如何將之前的採樣器響應數據保存到JMeter變量中:
vars.put(「ResponceData」,prev.getResponseDataAsString()); log.info(vars.get( 「ResponceData」));
基本上,這與vars
它相同,但它公開了JMeter屬性。有關java.util.Properties
更多信息,請參閱有關JMeter屬性的JavaDoc on 和JMeter文檔。的主要區別之間props
而且vars
是道具備一個「全局」範圍,而範圍vars
是有限的,以當前線程組。
log
表示Logger
類,可用於將消息附加到jmeter.log
文件中。如下是示例用例:
log.info(「使用INFO級別測試消息」); log.error(「使用ERROR級別測試消息」);
在某些狀況下,您可能但願根據響應添加參數。您能夠使用Beanshell預處理器執行此操做。
該sampler.addArgument()
方法容許您在手動訪問服務器以前添加參數。
如前所述,您能夠使用Beanshell動態更新JMeter變量。假設您有一個名爲「counter」的用戶定義變量,其值爲「1」。假設您但願每次在while循環中執行採樣器時將此計數器值遞增1。如下代碼段將計數器值遞增1並更新相同的值:
int counter = Integer.parseInt(vars.get(「counter」))+ 1; vars.put( 「計數器」,Integer.toString(計數器));
假設您須要調用用戶建立的類中存在的方法之一。您能夠使用Beanshell調用用戶建立的JAR文件中存在的方法。
lib/ext
JMeter的文件夾中。例如 :
鑑於您有如下課程:
package timeStampPack; import java.text.SimpleDateFormat; import java.util.Calendar; public class TimeStampConversion { public TimeStampConversion(){} public static String getTimeStamps(int count) { String dates =「」; for(int i = 1; i <= count; i ++) { try { Thread.sleep(1L); } catch(InterruptedException e){ e.printStackTrace(); } dates = dates +「TimeStamp」+ i +「==>」+ getCurrentDateTime()+「\ n」; } 返回日期; } }
在上面的類中,getTimeStamps()
方法返回timestamp,將其打包爲timeStamp.jar並將文件複製到lib/ext
JMeter安裝的文件夾中。
將Beanshell Sampler添加到測試計劃中,並將如下代碼放入「腳本」區域。
導入timeStampPack。*; var time = TimeStampConversion.getTimeStamps(1); log.info(時間);
上面的代碼將調用getTimeStamps()
方法並記錄該值。
您還能夠使用Beanshell使用CSV文件參數化測試數據。查看此文章以查看詳細信息。
JMeter是數千名開發人員使用的優秀開源負載測試工具。若是您是其中之一,則可能須要加載測試。JMeter可用於負載測試。使用RedLine13,您能夠在10分鐘內使用任何移動應用程序,Web應用程序或API的JMX腳本運行JMeter負載測試。
BeanShell is one of the most advanced JMeter built-in components. JMeter has rich built-in plugins which cover many needs of a performance test. For example, you might need some additional scripting while writing some complex tests. In such cases, it’s worth using Beanshell. In this post, we are going to be talking about testing complex logic with JMeter Beanshell and common use cases. Beanshell has the functionality to run java code and has access to JMeter APIs and external classes that are loaded in the JMeter classpath.
JMeter has the following Beanshell enabled components:
Beanshell Sampler.
Beanshell PreProcessor.
Beanshell PostProcessor.
__BeanShell function.
Beanshell Assertion.Below are the JMeter API classes exposed to Beanshell. If you look at the bottom of Beanshell, you’ll see the list of variables defined for the script.
You can access the member variables and methods of the
SampleResult Class in Beanshell.
For example, you can set and get the thread name using setThreadName()
and getThreadName()
methods respectively.
This class allows you to set response code manually. In some situations, you may need to set the response code based on the response that you get from server.
Here is a sample use-case:
if (condition) { ResponseCode = "200"; } else { ResponseCode = "500"; }
This class allows you to set the response message manually. The sample use case is the same as the one for ResponseCode
.
IsSuccess
is a Boolean
that reflects whether the sampler succeeded. If it’s set to true, the sampler is considered to have 「passed.」 Otherwise, it will be marked as 「failed」.
if (condition) { IsSuccess = true; } else { IsSuccess = false; }
ctx
is the most powerful variable exposed to BeanShell. It represents the
JMeterContext class, which is virtually JMeter itself. It provides read/write access to the underlying JMeter engine, samplers, and their results as well as variables/properties.
The following code demonstrates the usage of ctx variable:
log.info("Current Sampler class is: " + ctx.getCurrentSampler()); log.info("JMeter Engine class is: " + ctx.getEngine()); log.info("Previous Response Message is: " + ctx.getPreviousResult().getResponseMessage()); log.info("Previous Response Code is: " + ctx.getPreviousResult().getResponseCode()); log.info("Previous Response URL is: " + ctx.getPreviousResult().getURL()); log.info("Previous Response Time is: " + ctx.getPreviousResult().getTime()); log.info("Previous Domain is: " + ctx.getPreviousSampler().getDomain()); log.info("Previous Protocol is: " + ctx.getPreviousSampler().getProtocol()); log.info("Previous Port is: " + ctx.getPreviousSampler().getPort()); log.info("Previous Method is: " + ctx.getPreviousSampler().getMethod()); log.info("Thread Name is: " + ctx.getThread().getThreadName()); log.info("Thread Start Time is: " + ctx.getThread().getStartTime()); log.info("Thread End Time is: " + ctx.getThread().getEndTime()); log.info("Start Next Thread Loop on Error: " + ctx.getThreadGroup().getOnErrorStartNextLoop()); log.info("Stop Test on Error: " + ctx.getThreadGroup().getOnErrorStopTest());
Another use case is if you want to write all Assertions error to an HTML file so you can see which assertion is not working. You can use ctx
variable in Beanshell assertion to iterate through all samplers in the current context and write the failures in an html file.
Add a Beanshell assertion and copy the following code to write all the assertions to a html file:
import org.apache.jmeter.services.FileServer; f = new FileOutputStream("C:\\apache-jmeter-4.0\\bin\\result.html", true); pt = new PrintStream(f); pt.println("<html><body>"); for (a: SampleResult.getAssertionResults()) { if (a.isError() || a.isFailure()) { log.error("URL :"+ ctx.getCurrentSampler().toString()); log.error(Thread.currentThread().getName()+": "+SampleLabel+": Assertion failed for response: " + new String((byte[]) ResponseData)); pt.println("URL :"+ ctx.getCurrentSampler().toString()); pt.println(Thread.currentThread().getName()+": "+SampleLabel+": Assertion failed for response: " + new String((byte[]) ResponseData)); // update here what you want to write } pt.println("</body></html>"); pt.close(); f.close(); }
It’s an instance of the
JMeterVariables class and provides read/write access to current variables, is capable of enumerating/changing existing variables, creating new variables, and obtaining nested properties. All JMeter variables are Java strings. If you need to put something else to a JMeter variable, you’ll need to cast it to a string first. The following code snippet demonstrates how to save previous sampler response data into a JMeter variable:
vars.put("ResponceData", prev.getResponseDataAsString()); log.info(vars.get("ResponceData"));
Basically, this is the same as vars
, but it exposes JMeter properties instead. See JavaDoc on java.util.Properties
and JMeter documentation on JMeter properties for more information. The primary distinction between props
and vars
is that props have a 「global」 scope, whereas the scope of vars
is limited to the current thread group.
log
represents the Logger
class and can be used to append a message into jmeter.log
file. The following is the sample use case:
log.info("Test Message with INFO level"); log.error("Test Message with ERROR level");
In some cases, you might want to add parameters based on the response. You can do this using the Beanshell preprocessor.
The sampler.addArgument()
method allows you to add arguments before hitting the server manually.
As mentioned earlier, you can update JMeter variables on the fly using Beanshell. Assume that you have a user defined variable called 「counter」 with the value of 「1」. Let’s say you want to increment this counter value by one every time it executes a sampler in while loop. The following code snippet increments the counter value by one and updates the same:
int counter = Integer.parseInt(vars.get("counter")) +1; vars.put("counter",Integer.toString(counter));
Assume that you have a requirement to call one of the methods which is present in a user created class. You can call the methods present in user created JAR file using Beanshell.
lib/ext
folder of JMeter.For Example :
Given you have the following class:
package timeStampPack; import java.text.SimpleDateFormat; import java.util.Calendar; public class TimeStampConversion { public TimeStampConversion() {} public static String getTimeStamps(int count) { String dates = ""; for (int i = 1; i <= count; i++) { try { Thread.sleep(1L); } catch (InterruptedException e) { e.printStackTrace(); } dates = dates + "TimeStamp" + i + "==>" + getCurrentDateTime() + "\n"; } return dates; } }
In above class, getTimeStamps()
method returns timestamp, packages it as timeStamp.jar and copies the file to the lib/ext
folder of your JMeter installation.
Add Beanshell Sampler to your Test Plan and put the following code into the 「Script」 area.
Import timeStampPack.*; var time=TimeStampConversion.getTimeStamps(1); log.info(time);
The above code will call getTimeStamps()
method and logs the value.
You can also use Beanshell to parameterize test data using CSV file. Check this article to see details.
JMeter is an excellent open source load testing tool used by thousands of developers. If you’re one of them, you may want to load test. JMeter can be used for load testing. With RedLine13, you can run a JMeter Load Test with your JMX script of any mobile application, web application, or API in 10 minutes.