jmeter - showing the values of variables - variables

My group does a lot of test automation with JM. Typically we have a properties file which has a bunch of variables defined. These in turn are mapped to "User Defined Variables" of which we have a number of different sets.
These are in referenced throughout the rest of the jmx - I find it difficult as there are so many variables in so many different places to know what is what. Is there any way to have jmeter display what values its variables have - custom sampler is fine ? Ideally id love it if you could just hover a var and have its value displayed.
Any ideas ?

The newest versions of Jmeter have a fantastic sampler called "Debug Sampler" that will show you the values for: Jmeter Variables, Jmeter Properties or System properties.
You can insert them wherever you want in the script to get values at a given time. You'll want to have a "View Results Tree" enabled to view the sampler.
Given that Jmeter declares variables from a file on run, you won't be able to get your ideal solution.
I'm curious...would it be cleaner to employ "CSV Data Set Config" rather then populating "User Defined Variables" from a properties file?
Edit: Added explanation on variable declaration and asked CSV question.

Here is how I used to get Set of vars right through the code (variant with Java code in JSR223 PostProcessor):
Add "JSR223 PostProcessor" by right click wherever you need to check jMeter variables in your project;
Set Language (in my case - to java);
Add following code to Script window:
import java.util.Map;
String jMeterVars;
jMeterVars = "Quantity of variables: " + vars.entrySet().size() + ".\n\n";
jMeterVars += "[VARIABLE NAME] ==>> [VARIABLE VALUE]\n\n";
for (Map.Entry entry : vars.entrySet()) {
jMeterVars += entry.getKey() + " ==>> " + entry.getValue().toString() + "\n";
}
try {
FileWriter fw = new FileWriter("D:\\jMeterVarsForStackOverflow.txt",true);
fw.write(jMeterVars);
fw.close();
} catch(IOException ioe) {
System.err.println("IOException: " + ioe.getMessage());
}
Check that everything in the JSR223 PostProcessor looks like that:
Start your project in jMeter.
The code above will create jMeterVarsForStackOverflow.txt file at D: and put all variables there:

Related

How to set variables to custom function in Jmeter?

I have a basic function in BeanShellSampler.bshrc at Jmeter 4.0
String getMyString(String strParam) {
return "MyString: "+strParam;
}
I called in BeanShell Sampler as below
String N = "123123";
log.info("${__BeanShell(getMyString("${__V(Var${N})}"),)}");
When I run Sampler output is somthing like that.
2018-06-18 15:25:40,080 INFO o.a.j.u.BeanShellTestElement: MyString: Var${N}
How can I set string variable to my function?
I read function articles in Jmeter web site
Thank you.
Add the next line to user.properties file:
beanshell.sampler.init=BeanShellSampler.bshrc
Amend your code to look like:
String N = "123123";
log.info(getMyString(N));
That's it, you should get MyString: 123123 in jmeter.log file
Be aware that starting from Jmeter 3.1 it is recommended to use Groovy for all forms of scripting as Groovy performance is much better comparing to Beanshell so consider taking the following steps instead:
Create a file, i.e. foo.groovy in "bin" folder of your JMeter installation and put your function there:
String getMyString(String strParam) {
return "MyString: " + strParam;
}
Add the next line to user.properties file:
You should be able to refer your custom code from __groovy() function like:
${__groovy(log.info(getMyString("123123")),)}
functions can be used anywhere in the Test Plan
For each BeanShell Program type there are different beanshell.*.init properties defined in bin/user.properties
beanshell.function.init=BeanShellFunction.bshrc
beanshell.preprocessor.init=BeanShellSampler.bshrc
beanshell.postprocessor.init=BeanShellSampler.bshrc
beanshell.assertion.init=BeanShellFunction.bshrc
Hence the same function which needs to be called from any program(preprocessor, postprocessor, etc) we need to copy the function to every .bshrc file OR use same .bshrc file for every program init property.
In your case if you are using local string variable N and passing it along with the script. If you use ${Variable} there must be a JMeter variable defined so that JMeter can pick its value. To do that you can use vars.put , write N value to JMeter variables and use ${N} .
I have defined Var123123 value as FinalValue as shown below
And 2 beanshell samplers one is to put String variable N to Jmeter variable and one is beanshell script as shown below
You can see in the log its printed VAR123123's value which is FinalValue
The reason why i took 2 beashell samplers is if i write N to JMeter variables and use it in same script its not updating N value until the sampler executed..
References :
Configuring JMeter
JMeter Beanshell
Please let me know if it helps

Jmeter Beanshell: Accessing global lists of data

I'm using Jmeter to design a test that requires data to be randomly read from text files. To save memory, I have set up a "setUp Thread Group" with a BeanShell PreProcessor with the following:
//Imports
import org.apache.commons.io.FileUtils;
//Read data files
List items = FileUtils.readLines(new File(vars.get("DataFolder") + "/items.txt"));
//Store for future use
props.put("items", items);
I then attempt to read this in my other thread groups and am trying to access a random line in my text files with something like this:
(props.get("items")).get(new Random().nextInt((props.get("items")).size()))
However, this throws a "Typed variable declaration" error and I think it's because the get() method returns an object and I'm trying to invoke size() on it, since it's really a List. I'm not sure what to do here. My ultimate goal is to define some lists of data once to be used globally in my test so my tests don't have to store this data themselves.
Does anyone have any thoughts as to what might be wrong?
EDIT
I've also tried defining the variables in the setUp thread group as follows:
bsh.shared.items = items;
And then using them as this:
(bsh.shared.items).get(new Random().nextInt((bsh.shared.items).size()))
But that fails with the error "Method size() not found in class'bsh.Primitive'".
You were very close, just add casting to List so the interpreter will know what's the expected object:
log.info(((List)props.get("items")).get(new Random().nextInt((props.get("items")).size())));
Be aware that since JMeter 3.1 it is recommended to use Groovy for any form of scripting as:
Groovy performance is much better
Groovy supports more modern Java features while with Beanshell you're stuck at Java 5 level
Groovy has a plenty of JDK enhancements, i.e. File.readLines() function
So kindly find Groovy solution below:
In the first Thread Group:
props.put('items', new File(vars.get('DataFolder') + '/items.txt').readLines()
In the second Thread Group:
def items = props.get('items')
def randomLine = items.get(new Random().nextInt(items.size))

How to get the name of JMX Jmeter filename in a variable

I want to use the name of the jmeter test script (.jmx) in a listener so as to generate the result file in a dynamic way. Can you please tell me what is the Jmeter variable for that purpose?
Used ${fileName} which didn't work
You can do it via Beanshell scripting like:
GUI mode
import org.apache.jmeter.gui.GuiPackage;
String scriptName = GuiPackage.getInstance().getTestPlanFile();
vars.put("scriptName", scriptName);
non-GUI mode
import org.apache.jmeter.services.FileServer;
String scriptName = FileServer.getFileServer().getScriptName();
vars.put("scriptName", scriptName);
Put the code snippet of your choice into any "Beanshell" test element (sampler, pre/post processor, or assertion), it will get .jmx test script name and store it into ${scriptName} variable.
To learn more about Beanshell scripting in JMeter check out How to use BeanShell: JMeter's favorite built-in component guide.
The variable that holds the test plan name is ${__TestPlanName}
Ref: http://jmeter.apache.org/usermanual/functions.html#__TestPlanName
Below would work irrespective of GUI / Non GUI mode:
import org.apache.jmeter.services.FileServer;
import java.io.File;
String testPlanFile = FileServer.getFileServer().getBaseDir() +
File.separator +
FileServer.getFileServer().getScriptName();
props.put("testPlanFile", testPlanFile);
Use this as ${__P(testPlanFile)} - Adding it as var would not work across all threads. From http://jmeter.apache.org/usermanual/functions.html -
Properties are not the same as variables. Variables are local to a
thread; properties are common to all threads, and need to be
referenced using the __P or __property function.

BeanShell PreProcessor updates User define variables

I'm very new at JMeter issues.
In a test script i have a BeanShell PreProcessor element that updates some variables previously defined at a "User Defined Variables" element.
Latter those variables are used in "Http Requests". However, the value that is used in the http request is the default one.
The scripts seems to be working due to some debug print();
My question is if it's necessary to delay the script to be sure that the BeanShell finishes?
Thanks a lot for your attention
There is no need to put any delay to Beanshell Pre-Processor as it's being executed before request. I'd recommend to check your jmeter.log file to see if there are any scripting issues as Beanshell Pre-Processor does not report errors anywhere including View Results Tree listener.
There are at least 2 ways to assure that everything is fine with your Beanshell script:
Put your debug print code after variables replace logic to see if it fires
Use JMeter __Beahshell function right in your HTTP request. If it's ok - View Results Tree will demonstrate beanshell-generated value. If not - the field will be blank and relevant error will be displayed in the log.
Example test case:
Given following Test Plan structure:
Thread Group with 1 user and 1 loop
HTTP GET Request to google.com with path of / and parameter q
If you provide as parameter "q" following beanshell function:
${__BeanShell(System.currentTimeMillis())}
and look into View Results Tree "Request" tab you should see something like:
GET http://www.google.com/?q=1385206045832
and if you change function to something incorrect like:
${__BeanShell(Something.incorrect())}
you'll see a blank request.
The correct way of changing existing variable (or creating new if variable doesn't exist) looks like
vars.put("variablename", "variablevalue");
*Important: * JMeter Variables are Java Strings, if you're trying to set something else (date, integer, whatever) to JMeter Variable you need to cast it to String somehow.
Example:
int i = 5;
vars.put("int_i", String.valueOf(i));
Hope this helps.
You can update the vale of a "user defined variable".
You have to create a bean shell sampler
vars.put("user_defined_variable", "newvalue");
#theINtoy got it right.
http://www.blazemeter.com/blog/queen-jmeters-built-componentshow-use-beanshell
I'm new to jmeter too but as I know variables defined in "User defined variables" are constants, so you can't change them. I recommend to use "User Parameters" in preprocessors or CSV Data Set Config.

How to set a global Base URL for every test case of one test suite in Selenium IDE?

How to set a global Base URL for every test case of one test suite in Selenium IDE so that I can switch to different environment easily?
If you have a lot of test cases in a single suite, it's a pain to change the Base URL for each. Instead, create a separate case for each Base URL you need to switch between. For example, I have store https://testing.site.com/ as myEnvironment saved as test case SetEnvTesting. I create another case for my production site, SetEnvProduction.
Then, insert the ${myEnvironment} at the beginning of each relative URL in your test cases. For example, open ${myEnvironment}/login.aspx. (This might be a pain if you've got a lot of tests already. I suggest just adding it from now on.) Then, simply put the set-environment test case at the beginning of your test suite. To switch your entire suite to another Base URL, simply put a different set-environment case at the start. Another nice thing is that you can switch environments in the middle of the suite by putting a different set-environment case in the middle.
Edit: Example of using a SetEnvironment test case.
The SetEnvironment case:
An example of a following test case.
Notice
how the CurrentEnvironment variable is used. You can do this for every case in the suite. Additionally, you can make every separate test suite use this same SetEnvironment case, so they all switch together.
that the Base Url becomes irrelevant. You're overriding it, essentially.
I hope that's helpful!
The test case HTML file is responsible for setting the base URL. From the Selenium IDE, you can override the base URL for a test case. A test suite, on the other hand, is only a bag for your test cases.
Remove the base URL setting from each of the test case files referenced from your test suite. Then set the base URL by hand for the test suite and run the suite.
The line in question is in the head of each test case file:
<link href="http://server-name/" rel="selenium.base"/>
If it is missing, then the base URL overrides it automatically.
I found it exceedingly frustrating that I couldn't just have a blank Base URL and have it use whatever page I already had open as the start of the test. What is the point of being able to record relative URLs when it forces you to hardcode a base url that is prefixed to every relative url (thus turning them into absoulte urls)??
Extending on the other answers and from this question: In Selenium IDE, how to get the value of the base url
You can store the current domain in a variable and then use that instead of a hard coded one. This lets you login to the server you want to run the tests on, hit play and it will run the tests without all this baseURL nonsense redirecting you to the wrong server.
Just use these commands at the start of the first script in your suite:
And keep using the http://${host}/ syntax for every truly relative URL you need in your script.
I just created a separate test and put it at the top of all tests. Store the base url to an variable and now I am able to access it in other test cases by ${variable_name}.
I tried the accepted answer, it does work for selenium IDE, but it does not work when running stand-alone server.
finally, I put the value inside the user-extensions.js , and use storeEval to get the value back. Then the same value could be retrieved inside different cases.
EDIT:
In the user-extensions.js, add the following
var selenium_base_url = "http://example.com"
In the HTLM suite, add the following
<tr>
<td>storeEval</td>
<td>selenium_base_url</td>
<td>case_base_url</td>
</tr>
<tr>
<td>open</td>
<td>${case_base_url}/case_path?a=1&b=2</td>
<td></td>
</tr>
This may look odd at the first sight, but actually user-extension.js could be modified on the fly right before the stand-alone server execution, so you may put a different base url using a script in the real QA scenario.
Hmm, I think there is a simpler solution:
In the first test (of the test suite) adjust
<link rel="selenium.base" href="http://google.com" /> as needed
In the following tests remove (using text editor or similar):
<link rel="selenium.base" ... />
If you're fine double clicking multiple times,
Double click the top one, set it to the URL you want.
Now double click the top, middle, bottom.
Now double click the bottom, middle, top.
I created a user-extension command 'doBaseURL' that manipulates the Selenium IDE field 'Base URL'.
In every test case of a test suite I added this command | baseURL | | |. Below the surface it sets a stored variable named baseURL.
It is possible to give the stored variable 'baseURL' a value from a test case command prior to the first 'baseURL' command.
This method overwrites the <link href="http://server-name/" rel="selenium.base"/> setting of each test case file.
For me this works fine as now the Selenium IDE reflects the Base URL that the test case(s) will use (or was using when an error occured).
The java script is:
Selenium.prototype.doBaseURL = function(strTarget, strValue) {
/**
* Enables a more predictive Base URL when running a test suite with multiple test cases.
* On first usage it wil fill a stored variable 'baseURL' either with the given strTarget,
* or when not given with the Base URL as shown on the Selenium IDE UI. The Selenium IDE UI field
* Base URL is updated to reflect the (new) base URL.
* In each subsequent test case with a baseURL command the stored variable 'baseURL' will determine
* the base.
*
* <p> Best to use as first command in each test case and only in the first test case a strTarget
* argument, in that way the test cases of a test suite will no longer depend on their 'hidden'
* '<link rel="selenium.base" href="http://www.something.com/" />
* construction, that makes test cases effectively having an absolute base URL.
* </p>
*
* #param strTarget a Base URL value to be used in the test case (e.g. https://www.google.com/)
*/
// pushes the given strTarget into the selenium.browserbot.baseUrl
// and makes the new Base URL value visible on the Selenium IDE UI.
// A subsequent open command will use this new Base URL value
LOG.debug("begin: doBaseURL | " + strTarget + " | " + strValue + " |");
// note: window.location.href = strTarget; causes the browser to replace Selenium-IDE UI with the given url
// used that knowledge to manipulate the Selenium IDE UI as if a manual Base URL change was done.
LOG.debug("window.location.href= [" + window.location.href + "]");
LOG.debug("window.editor.app.getBaseURL() gives [" + window.editor.app.getBaseURL() + "]");
if (strTarget && (strTarget.substring(0,1)!="$")) { // only when strTaget has a value
strValue = "Base URL changed from [" + selenium.browserbot.baseUrl.toString() + "] into [" + strTarget + "]";
selenium.browserbot.baseUrl = strTarget.toString();
// set the visible Base URL value on the Selenium IDE UI to the new value
window.editor.app.setBaseURL(strTarget);
LOG.debug("updated into: " + window.editor.app.getBaseURL());
// remember this value for future calls
storedVars["baseURL"] = window.editor.app.getBaseURL();
LOG.debug("storedVars[\"baseURL\"] set to [" + window.editor.app.getBaseURL() + "]");
} else {
// no value => take storeVars["baseURL"] when set;
// otherwise take Selenium IDE Base URL field.
if ((storedVars["baseURL"] != undefined) && (storedVars["baseURL"] != "")) {
strValue = "Base URL changed from [" + selenium.browserbot.baseUrl.toString() + "] into [" + storedVars["baseURL"] + "]";
selenium.browserbot.baseUrl = storedVars["baseURL"];
// set the visible Base URL value on the Selenium IDE UI to the new value
window.editor.app.setBaseURL(storedVars["baseURL"]);
LOG.debug("updated from storedVars[\"baseURL\"]");
} else {
strValue = "Base URL changed from [" + selenium.browserbot.baseUrl.toString() + "] into [" + window.editor.app.getBaseURL() + "]";
selenium.browserbot.baseUrl = window.editor.app.getBaseURL();
// remember this value for future calls
storedVars["baseURL"] = window.editor.app.getBaseURL();
LOG.debug("storedVars[\"baseURL\"] set to [" + window.editor.app.getBaseURL() + "]");
}
}
LOG.info(strValue);
LOG.debug("end: doBaseURL | " + strTarget + " | " + strValue + " |");
}
Installing a user-extension script is explained in the "Using User-Extensions With Selenium-IDE" section SeleniumHQ documentation: http://www.seleniumhq.org/docs/08_user_extensions.jsp