Jmeter how to loop through a list of different properties in a single thread group or controller? - loops

How to do a basic loop through different properties for a fixed set of controllers? Loop controller runs a set group a certain number of times, does not use properties though.
I can do modules, and set the values to properties for multi thread group usage, but how to pass the next iteration of the property, and run the loop again?
property x
do module (points to controllers)
next property
Say I have a list of 44 characters, and I want to loop through those characters in a ${name} while I'm doing a test. I'd very much not like to build 44 sets of controllers for one character change.
Please Note I cannot add extra files to my computer. It has to work via the stock available controllers. I'm using Jmeter 2.4 r961953
Thanks

I will elaborate slightly more about the BeanShell method. My assumption is that you'd like to do it within one User Thread, if so my proposal would be:
Create a Loop Controller.
Logic Controller->Loop Controller
Inside Loop Controller add following entries:
Config Element -> Counter
Preprocessors -> BeanShell preprocessor
Sampler -> yourSampler
The Counter element will be used as an index that will be used to choose valid value from our array, hence we need to specify a Reference Name for the Counter - let's say that it will be loopCounter.
Now we have to switch to BeanShell preprocessor and define the array of values. A great thing is that we have vars variable available and it gives us CRUD access to variables used in the scenario:
String[] varArray = {"Value1", "Value2"};
idx = Integer.parseInt(vars.get("loopCounter"))-1;
vars.put("myVariable", varArray[idx]);
And for the final step, inside mySampler we can use a variable in a regular JMeter way : ${myVariable}
JMeter API can be very helpfull if you want a more sophisticated solution.

There are a handful of different ways to loop through different values without adding external files:
Use beanshell controller, and write javascript to set your variable
Use a counter to increment by one
Use User Parameters
You can set it up so each loop gets a different value.
Check out the various configuration controllers to find one that works best for you.
EDIT:
I meant user parameters, not user define variables.
User Parameter
You'd need one row per variable with 44 columns. Sorry for the confusion.
User Parameter Structure
test plan
- Thread Group looped 44 times
-- User parameter
-- Request
Beanshell Method
Alternately, you could do an array in javascript in connection with a counter. The Beanshell samplers have access to Jmeter variables and properties, allowing the beanshell sampler to read the counter value. This may be a faster, cleaner way then using User Parameters.
Beanshell structure
test plan
- Thread Group looped 44 times
-- Counter
-- Request
---- Beanshell pre-processor
Beanshell Pseudo code would be
def counter = value of Jmeter Counter
def array = array of values
declare the variable "sampler_value" to be used by sampler
def sampler_value = array # counter
Counter with CharAt function
If you only need to generate characters, you could use the javascript function to utilize the function charAt, using the value from the Counter. Basic structure would be:
test plan
- Thread Group looped 44 times
-- Counter
-- Request
with the request using something like ${__javaScript(charAt(${counter})) as the parameter value. You may have to use JEXL instead of javaScript or evalVar/V/eval inside the charAt function.

Related

Sending muliple occurrences of id to a request in jmeter

From a soap XML response I need to get all the occurrences of an id (This part already done using Match No being set to -1 in Regex extractor).
And then I need to send these ids to a subsequent request. That is, the request needs to be fired as many times as of the total number of occurrences of the id, we can call it as ID_matchNr. (This is the total occurrences I got from the Regex extractor).
I used a while loop and a counter. The while loop works until the ID_matchNr, but it doesn't stop there, that while loop is infinite. How to fix this?
My counter's reference name is count and the field name in my request is ${__V(ID_${count})}. And while loop's condition is ${count}<=${ID_matchNr}. I also tried using a beanshell to save the ID_matchNr to another variable and then use it in while condition instead of directly using ID_matchNr. Still running infinitely.
Have you considered using ForEach Controller?
Given you have JMeter Variables in form of:
ID_1=foo
ID_2=bar
ID_3=baz
ID_matchNr=3
Add ForEach Controller to your Test Plan and configure it like:
And put the "subsequent" sampler as a child of the ForEach Controller and refer the generated subsequent ID value as ${CURRENT_ID} where required
More information on the concept with the real-life example: Using Regular Expressions in JMeter

Is Angular's foreach loop over an object asynchronous?

I read somewhere in the past that angular.foreach is asynchronous unlike looping over arrays which is synchronous. For a long time I was taking into account this and doing the necessary to avoid executing the code which comes after the loop before it's finishes all its iterations (by wrapping the angular.foreach inside an anonymous JavaScript function which calls a callback which will be executed once the loop finishes all iterations).
(function(callback){
angular.foreach(..)
callback();
})(callback)
But I had a conversation with a collegue who didn't agree that angular.foreach is asynchronous and I also couldn't find that information again which makes me confused now.
no. Take a look at the docs
Furthermore your code wouldn't work if foreach would be asynchronous.
If foreach would be async, the callback would be called immediately after calling foreach and foreach would be put onto the eventqueue which would execute it some time in the future.
Javascripts concurrency model does not have threads but instead uses an eventloop. This means every async operation is pushed onto the eventqueue and executed later.
Have a look into the MDN
There may be a scenario where you want to make code behave asynchronously.
I had a scenario where I used local storage to store an ad-hoc user selected collection of jobs that I wanted to perform the same operation on.
I had a web service call to convert a list of job names into a returned a collection of job objects. I initially tried using a
foreach loop inside the subscribe pf the service layer, that operated on the results.
Then I tried calling another method within the foreach loop that as it performed the operations removed the job name from local storage when the operation posted to the web service correctly.
The problem was on the second iteration I read the collection of names from local storage again - before the set to remove had completed.
There was a lot of manipulation of the job and object properties to create the parameters passed on the function call, so I ended up refactoring the code, creating a value object interface and stored the information in a value object array for the whole job collection I had returned. I included the index of the job too in the value object.
I introduced a BehaviourSubject property to the class.
During the restructuring, I just added an entry to the value object array collection within the forEach loop instead. At the end of the loop. I sent next(0) to the BehaviourSubject to start the ball rolling.
Each time a job name was removed from local storage, I converted service to return a Promise.
Then in the code after the service was called I put this code in the then part, behaviour subject.next(index from value object +1)
In the initialisation I set the behaviour subject up with a -1 value..
Then in the subscription to the BehaviourSubject class I ignored -1,
And when the index +1 was > length of value object collection called completion routine - which bounce app back to prior page.
When the index was between 0 and 1 less than collection size, I just called the method that had originally been in the forEach loop with the value object entry with the value object match the index of the behaviour subject.
By doing this I had converted the behaviour of the forEach into something asynchronous.

Jmeter Property with array of values

Requirement: Need to store 50+ values to a Jmeter property and use with idx
In the case of normal variable we can use Country_1 or Country_2.
Do we have any function to set an array of values to jmeter Property and how to get value using index?
Note: In this case,value has to be used in different thread group.
Your ArrayList initialization is not correct, you should be doing something like:
List myList = Arrays.asList('India', 'USA', 'UK')
There is no putObject method in props shorthand (which is basically an instance of java.util.Properties class so you will need to amend your code like:
props.put('Middle', myList)
Once done you will be able to access individual list members using __groovy() function like:
${__groovy(props.get('Middle').get(0),)} - for first member
${__groovy(props.get('Middle').get(1),)} - for second member
${__groovy(props.get('Middle').get(2),)} - for third member
etc.
Demo:
See Apache Groovy - Why and How You Should Use It article for more details on using Groovy scripting in JMeter tests.

JMeter - loop controller with variable loop count

I am using JMeter and I want to define one loop controller. In this loop I want to define the loop count with a Jmeter variable. Is this posible?
Thanks a lot
I know is very late to help you, but it can help the others.
One good way to do this is to define a counter inside the loop controller.
Example, if you want a loop with 20 iterations, you put 20 in the loop controller and in the counter you put from 0 - 19. In the counter you can also define an increment. The output variable is named in the Reference Name field.
Yes, it's possible.
Define your user variable using the User Defined Variables component, or use the CSV component.
Then, in the Loop Controller, define loop count to: ${nameOfVar}
Since version 4.0 of JMeter, there is an easier way:
https://jmeter.apache.org/usermanual/component_reference.html#Loop_Controller
JMeter will expose the looping index as a variable named
__jm__Name of your element__idx
So for example, if your Loop Controller is named LC, then you can access the looping index through ${__jm__LC__idx}. Index starts at 0
If you're looking to learn jmeter correctly, this book will help you.
You can use the following inside the "Loop Count" field:
${myVar}
e.g. for a random count:
${__groovy(java.util.concurrent.ThreadLocalRandom.current().nextLong(128L),)}
You can access the current loop index (starts at 0) via ${__jm__Loop Controller__idx} where Loop Controller is the name of your loop.

changing variables in loop in Jmeter

I have web request like this
Loop Controller(3)
moreSamples=true
startIndex=0
While Controller(${__javaScript(${moreSamples}==true)})
SOAP/XML-RPC Request(index=${startIndex})
Regular Expression Extractor(startIndex=newIndex,moreSamples=samples)
Now problem is I am not able to initialize moreSamples and startIndex in loop.
I tried two options:
Make moreSamples and startIndex as user defined variables. Now I am able to change their values using Regular Expression Extractor but not able to reinitialize them in outer loop using BeanShell PostProcessor like this:
vars.put("moreSamples","false")
vars.put("startIndex","0")
Make moreSamples and startIndex as User Parameters in preprocessor of of while loop but then I am not able to assign them values using Regular Expression Extractor.
Please suggest the mistakes or some new construct which can fit in.
Screenshot:
#bpsingh,
Can you do following things:
Add UserDefinedVariables on top of your Test Plan with two defined variables:
moreSamples, startIndex (like #ant suggested already)
Under the Download - PersistentSyncScope Sampler, you have two regular expression extractors in which I assume you want to extract some values and place it in these two variables from the above. Add BeanShellPostProcessor under the Download - PersistentSyncScope Sampler.
In BeanShellPostProcessor add following code:
vars.put("moreSamples","${REGEX_EXTRACT1}");
vars.put("startIndex","${REGEX_EXTRACT2}");
These two (moreSamples, startIndex) are global variables and changes on them should be visible outside of the loop.
Do you have to initialize them from the loop? How about adding those to User Defined Variables?
Or you can do it from your loop as well, the reason why it doesn't work for you is either the fact that you forgot to put the semi-colon ; after your expression(s) :
vars.put("moreSamples","false"); // ; <- was missing
vars.put("startIndex","0"); // ; <- was missing
I used BSF Sampler and it worked for me (don't forget to choose the language -> beanshell if you use this one). Here is my debug sampler (relevant part) :
START.HMS=101818
START.MS=1341821898080
START.YMD=20120709
TESTSTART.MS=1341822195274
moreSamples=false
startIndex=0
Update:
You need not to use both BSF Sampler and user defined variables. You can use either, and I see you have more user defined variables, no need for that. Have one of those at the start of your test. I'm still not clear what your problem is and what you're trying to achieve.
Actually problem here is I am using 2 loops and all answers don't take this properly into account.
Since pre/post processors are applied only to samplers not to loops there is no way to reinitialize the variables before while loop. Thus if I add initialize statements in preprocessor, loop run infinitely and if in postprocessor, it never executes. Only way to initialize is adding BSF sampler before while loop but that will spoil the reports as this sampler will also be recorded by listeners.
So only solution I found is run Download - PersistentSyncScope Sampler once and add BSF preprocessor with following scripts
vars.put("moreSamples","false");
vars.put("startIndex","0");
Now add while loop and add Download - PersistentSyncScope Sampler as its child.
That is the only solution till now. Thanks everyone to help me understand the problem.

Resources