I have a script where I have some if controllers. I'm attempting to add a 4th If controller that will trigger a script failure if none of the 3 expected values is returned. It's saying one of the 3 expected values is invalid.
1st, I have a user defined variable like this:
testTool= ${__P(testTool,APPLES)}
2nd, I have these 3 If controllers with these Expressions:
${__groovy(vars.get("testTool").toUpperCase().equals("APPLES"))}
${__groovy(vars.get("testTool").toUpperCase().equals("BANANAS"))}
${__groovy(vars.get("testTool").toUpperCase().equals("PEACHES"))}
The 4th If is supposed to be triggered if the value of testTool is not one of the 3 expected values. It's Expression looks like this:
> ${__groovy( (vars.get("testTool").toUpperCase().equals("APPLES") == false ||
> vars.get("testTool").toUpperCase().equals("BANANAS") == false ||
> vars.get("testTool").toUpperCase().equals("PEACHES") == false)) }
I have also tried it this way:
> ${__groovy((!vars.get("testTool").toUpperCase().equals("APPLES") ||
> !vars.get("testTool").toUpperCase().equals("BANANAS") ||
> !vars.get("testTool").toUpperCase().equals("PEACHES")),)}
It is somehow saying APPLES is an invalid testTool. What am I doing wrong? All if controllers have the 'Interpret Condition as Variable Expression' checked.
Use the following condition in if controller
${__groovy(!(vars.get("testTool").toUpperCase().equals("APPLES"))||!(vars.get("testTool").toUpperCase().equals("BANANAS"))||!(vars.get("testTool").toUpperCase().equals("PEACHES")))}
Please let me know if it helps
You should use && operator instead of ||, see Groovy Logical Operators for detailed explanation and more information.
Your 4th expression needs to be amended to look like:
${__groovy(!(vars.get("testTool").toUpperCase().equals("APPLES")) && !(vars.get("testTool").toUpperCase().equals("BANANAS")) && !(vars.get("testTool").toUpperCase().equals("PEACHES")))}
An easier option would be using Switch Controller, from implementation and especially performance perspectives it is the optimal solution.
Add Switch Controller to your Test Plan
Use ${testTool} as the "Switch Value"
Put 4 requests as the children of the Switch Controller and name them as:
APPLES
BANANAS
PEACHES
DEFAULT
So if ${testTool} variable value will be APPLES - the APPLES sampler will be executed, if ${testTool} variable value will be BANANAS - the BANANAS sampler will be executed, etc.
If ${testTool} will not match any other children - JMeter will run DEFAULT sampler
See Selection Statements in JMeter Made Easy guide for details.
Related
I have my HTTP request and have some conditions need to wait get at least 1 results or complete=true from the response.
I also want to add if keep executing to satisfy the below condition I want to stop after some request, my code:
if (vars.get('complete') == true || vars.get('total_result') > 0) {
vars.put('stop', true);
}
My request:
I think you are getting a String when getting vars value and failed to compare to 0.
You can parse value as Integer:
int total_result = vars.get('total_result') == null ? 0 : Integer.parseInt(vars.get('total_result'))
if (vars.get('complete') == true || total_result > 0) {
vars.put('stop', true);
}
You have a significant number of errors in the jmeter.log file:
so first of all you need to analyze what's going on there, it might be the case the variables are not having respective values.
Also since JMeter 3.1 you're supposed to be using Groovy language for scripting so consider migrating from JavaScript, moreover it is not available in later Java versions
Also JMeter Variables are stored as Java Strings so you need to perform the strings comparison or conversion of values to the required types
Suggested clause change (again assumes Groovy language):
vars.get('complete') == 'true' || (vars.get('total_result') as int) > 0
I am trying to write logic for a search query. There are many different conditions with different parameters. One parameter sent from form is code. So there are code values in two different tables: competitions and responses. What I need is to check the params[:code] value first in competitions table and if it does not exist then check in responses table. If it does not exist in either table then it should return nil. I am trying to write it in a single if statement. The code I tried is below:
competitions = Competition.includes(:event, :responses)
if params[:code].present?
competitions = (competitions.where(code: params[:code])) ||
(competitions.joins(:responses).where(responses: { code: params[:code] }))
The above code checks only the value of competitions.where(code: params[:code]). If that value is [], then it is not evaluating the second condition. What changes should I do to make the above code work as per the requirements mentioned above?
competitions.where(code: params[:code]) returns a Relation object which is always truthy.
Luckily enough, it implements #presence method, returning either the value if it’s not blank, or nil. So, this should work:
competitions.where(code: params[:code]).presence || ...
How to achieve a kind of mapping between string and numeric values that can be used for comparison in assertion? Example:
MAP "DELIVERED"=0
"PENDING"=1
"WAITING"=2
sampler1 - extracted numeric_value=0
sampler2 - assert string value="DELIVERED" is equal to its numeric value
Please check the below test plan:-
I have used variable name from regular expression of 1st sampler in the switch controller like ${regVar}..Then used the second request 3 times i.e. 0,1,2 and used response assertion with the desired value like "DELIVERED"=0 for first sampler under switch i.e "0" then in second "PENDING"=1 i.e "1"..so on.
With this, based on the regEx value from 1st http sample, only one http request will be send for 2nd sampler and that request have it own assertion. I have tried with both positive and negative cases. Please change the assertion value based on your requirements.
Please check if it helps.
Be aware of JSR223 Assertion which allows you to use arbitrary Groovy code to define pass/fail criteria.
You can access the numeric_value using vars shorthand for JMeterVariables class like:
def numericValue = vars.get('numeric_value')
Example code:
def myMap = ['0':'DELIVERED', '1':'PENDING', '2':'WAITING']
def numericValue = vars.get('numeric_value')
log.info('Numeric value is: ' + numericValue)
log.info('Status is: ' + myMap.get(numericValue))
Demo:
More information: Scripting JMeter Assertions in Groovy - A Tutorial
Thanks Dmitri, implemented solution based on your suggestion and it suites fine.
I have a request in Jmeter that I need to loop until I find the result I am looking for. I have read a few bits about a while controller but found them unhelpful as they seem to glance over vital information or are using an older version of Jmeter
I'm currently using Jmeter 5.0, and I have attempted to implement a while controller but failed as I think I do not understand how to properly handle the response, or even grab it, and then use it as a comparison to assert if the item exists.
I get a response from the HTTP request call response that looks a little somthing like this:
{"data":{"getIDs":{"Page": 1,"PageSize": 25,"PageCount": 1,"isFirstPage": true,"batches":[{"id":"b601a257-13fe-4de3-b779-a5922e89765a"},{"id":"b601a257-13fe-4de3-b779-a5922e89765b"},{"id":"b601a257-13fe-4de3-b779-a5922e89765c"}]}}
I need to recall the endpoint until I have found the ID I am looking for or cancel after 10 attempts
So after a bit of fumbling around I, I figured on my own answer that seems to work well. But I would suggest looking at other sources before taking mine as gospel.
The basic structure looks as follows:
Within a thread I set the variables then create the while loop as the next step. Within the While loop I created a counter then added the request I wanted to loop after. To make the loop work for me, I have three items sat under the request.
A Response Assertion: this check for a 200 status as the call should never fail
A Constant Timer: There is a delay between polls of the end point
A JSR223 Assertion: groovy code used ensure the while loop logic is handled
User Defined Variables:
Here i have setup two variables:
DONE: Done is a string value I alter if my JSR223 Assertion finds the values I'm looking for in the HTTP request
MyValue (this is dynamically driven in my actual test, for demo purpose, I’m just declaring a value to look for i.e. 12345)
While Controller:
I still feel i may not understand this correctly, however after some googling I came across the following code that works for me despite some errors in the JMeter console:
${__javaScript(("${DONE}" != "yep" && ${Counter} < 10),)}
This code is saying that the while loop will continue until either of these two conditions are met:
DONE, the variable created earlier, is equal to the value yep
Counter is less than 10 (Counter is declared beneath the while loop)
Counter:
this was a simple configuration step that just worked once I understood it needed to be within the while loop, i configured the following:
Starting value = 1
Increment = 1
Exported Variable Name = Counter
Ticked 'Track Counter independently for each user'
Ticked 'Reset counter on each thread group iteration'
(Exported Variable Name: you can call this whatever you want, I’ve named it counter for the purpose of this demo)
JSR223 Assertion:
This is a simple script assertion that just uses a Boolean and a couple of if statements to assert the state of the test.
import org.apache.commons.lang3.StringUtils;
def done = vars.get("DONE");
String response = prev.getResponseDataAsString(); //retrieves the http request response as text
String MyValue = vars.get("MyValue");
def counter = vars.get("Counter");
//Find Substring within response string and stor result as boolean
String container = response;
String content = MyValue;
boolean containerContainsContent = StringUtils.containsIgnoreCase(container, content);
//Check if the true condition is met and change the value so the loop exits
if (containerContainsContent == true){
log.info("------------------------Got Here");
vars.put("DONE", "yep");
}
//Force test to fail after 10 loops
if (Counter.toString() == "10"){
assert 1 == 2
}
I am running a ForEach controller in which I want the controller to run the service underneath it for changes in sets of latitudes and longitudes. example-
Input variable prefix: latitude
Output variable name: Latitude
I want to run the controller for changes in both "latitude" and "longitude". I tried doing this-
Input variable prefix:latitude, longitude
but it does not work. Is there any other way to pass two variables in ForEach controller?
Unfortunately you cannot do it using ForEach Controller, but you can work it around using __V() and __counter() function combination.
For example you have 4 JMeter Variables:
latitude_1=40.7128° N
longitude_1=74.0059° W
latitude_2=32.0853° N
longitude_2=34.7818° E
And you want to iterate them both using ForEach Controller. In that case the relevant configuration would be:
Input variable prefix: latitude
Output variable name: anything meaningful, i.e. current_latitude
You can refer matching longitude value using the following expression:
${__V(longitude_${__counter(,)})}
Demo:
See Here’s What to Do to Combine Multiple JMeter Variables for detailed explanation of where did the above expression come from.
I encountered same problem and google a lot to find the best possible solution but
did not get success. I am sharing my work-around (and I am not saying it's a great solution ) -
Mention your Input variable name (ex - inputVar) as well as Output variable name (outputVar) on ForEach Controller
(lets say http://website.com/folder_A/folder_B/123_latitude/456_longitude) and you like to take care these two : latitue and longtitude
Use regular expression extractor :
Name of created variable : inputVar
Expression : http://website.com/folder_A/folder_B/(.*)
Template : $1$
match No : -1 // (yes -1 , this will give you complete group)
Handle with regular expression (just search it out )
so for above example : that would be -
http://website.com/folder_A/folder_B/${outputVar}
http://website.com/folder_A/folder_B/${outputVar} URL will be able to print / give you latitue and longtitude in your response code