Jmeter, Groovy JSON slurper for Keys that are variables - json

I just recently read that using vars.get("variable") is much more efficient than using ${variable}. I had experience using the latter but it results in an error, but I already managed a work around it so that the error will no longer occur (I will no longer discuss it since it is not my issue here). Here is the part of the code:
import groovy.json.JsonSlurper;
String response = prev.getResponseDataAsString();
def jsonSlurper = new JsonSlurper();
def json = jsonSlurper.parseText(response);
if (json.data.target_list) {
Random random = new Random();
String[] strLeadDBIDList = json.data.target_list.keySet();
int idxLeadDBID = random.nextInt(strLeadDBIDList.length);
String strLeadDBID = strLeadDBIDList[idxLeadDBID];
log.info("Leads Dashboard - Customer ID: " + strLeadDBID);
vars.put("strLeadDBID",strLeadDBID);
String strLeadDBModule = json.data.target_list."${strLeadDBID}".parent_type;
log.info("Leads Dashboard - Customer Type: " + strLeadDBModule);
vars.put("strLeadDBModule",strLeadDBModule);
...
So my question, is there a way to use vars.get("strLeadDBID") instead of "${strLeadDBID}" in the String strLeadDBModule = json.data.target_list."${strLeadDBID}".parent_type; code? Or can I use the variable strLeadDBID instead, and how? Thanks!!!

My expectation that it would be something like:
String strLeadDBModule = json.data.target_list.get(vars.get("strLeadDBID")).parent_type;
If it will not work do the following:
log.info('Target list class name: ' + json.data.target_list.getClass().getName()))
and look for the relevant line in jmeter.log file. Then check JavaDoc for the given class in Groovy GDK API documentation and look for a suitable function.
Also as per JSR223 Sampler documentation
When using this feature, ensure your script code does not use JMeter variables directly in script code as caching would only cache first replacement. Instead use script parameters.
You could try the below setup:
Check out Apache Groovy - Why and How You Should Use It article for more hints on using Groovy scripting in JMeter tests

Related

JMeter: Update Empty JSON hashmap groovy

Response from http request:
{"Preferredvalue":{"notations":[]}}
def response = new groovy.json.JsonSlurper().parse(prev.getResponseData())
I am able to get up to notations and also the size.
If the size is 0, I want to update the notations as below
{"Preferredvalue":{"notations":[{"Name":${firstName},"lName":${lastName}}]}
firstName and lastName are Jmeter variable which are fetched from another calls, and I want to use these values in my another call and send a PUT request.
Searched a lot but couldnt find an answer :(
Best,
Something like:
def response = new groovy.json.JsonSlurper().parse(prev.getResponseData())
def notations = response.Preferredvalue.notations
if (notations.size() == 0) {
notations.add([Name: vars.get('firstName'), lName: vars.get('lastName')])
}
def request = new groovy.json.JsonBuilder(response).toPrettyString()
vars.put('request', request)
should do the trick for you. Refer generated value as ${request} where required
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy: What Is Groovy Used For?

How to run groovy script in Blazemeter, which try to get access to csv file data?

I have some Jmeter script on groovy
1.upto(${amount_of_items}, { index ->
def data = new File('data/ids.csv').readLines().get(index).split(',')
def attr = [:]
attr.put('id', data[0].toInteger())
def attributes = [:]
def param = [:]
param.put('quantity', ${quantity})
param.put('status_id', 4)
attributes.put('statuses', [param])
attributes.put('identity', attr)
adjustItems.add(attributes)
})
Is there any solution to get access to my csv which I try to parse from Blazemeter?
def data = new File('data/ids.csv').readLines().get(index).split(',')
Could I upload my csv to Shared Folder in Blazemeter and use it in script?
There shouldn't be a problem to access your file in BlazeMeter given you upload it to the shared folder. See Shared Folders article for more details.
Also according to JSR223 Sampler documentation:
The JSR223 test elements have a feature (compilation) that can significantly increase performance. To benefit from this feature:
Use Script files instead of inlining them. This will make JMeter compile them if this feature is available on ScriptEngine and cache them.
Or Use Script Text and check Cache compiled script if available property.
When using this feature, ensure your script code does not use JMeter variables or JMeter function calls directly in script code as caching would only cache first replacement. Instead use script parameters.
So I would recommend amending your code to use vars shorthand for JMeterVariables class instance like:
1.upto(vars.get('amount_of_items') as int, { index ->
def data = new File('data/ids.csv').readLines().get(index).split(',')
def attr = [:]
attr.put('id', data[0].toInteger())
def attributes = [:]
def param = [:]
param.put('quantity', vars.get('quantity') as int)
param.put('status_id', 4)
attributes.put('statuses', [param])
attributes.put('identity', attr)
adjustItems.add(attributes)
})

How to extract the Substring from URL present in JSON response using JMeter

I've the below JSON response received from the HTTP request. I want to extract the parameters from the node "url" present in the JSON response.
{"Id":"7S9LyBqyv1e0trKrVuP1OOZGHeg","Url":"https://abcd.com:443/u/custom-response?prov=34545sdf-9013e2e61e66&realmeId=%2Fxxxx","realmeId":"/abcd"}
In the above JSON response, i want to retrieve the value of "prov" which is 34545sdf-9013e2e61e66 using JMeter.
Solution Tried: Used Beanshell to read the response.
String url = vars.get("successURL");
vars.put("responseURL",url.toString());
responseURL = responseURL.replaceAll(":"," ");
log.info("String URL "+responseURL.toString());
Error Message:
attempt to resolve method: toString() on undefined variable or class name: responseURL
I think you need to update this line:
responseURL = responseURL.replaceAll(":"," ");
to something like:
responseURL = vars.get("responseURL").replaceAll(":"," ");
However I don't guarantee that it will work because I don't know how do you get this successURL variable.
What will work is doing everything in one shot using JSR223 PostProcessor and Groovy language which has built-in JSON support, suggested code:
def url = new groovy.json.JsonSlurper().parse(prev.getResponseData()).Url
def params = org.apache.http.client.utils.URLEncodedUtils.parse(new URI(url), 'UTF-8')
params.each { param ->
log.info(param.getName() + '=' + param.getValue())
}
Demo:
More information: Apache Groovy - Why and How You Should Use It
You don't need to use complex Beanshell coding, You can do this easily using - Regular Expression Extractor.
Here the example:-
You can see required value extracted and stored in variable name give in Regular expression extractor:
To understand try out reg-ex, you can use https://regex101.com/

Parsing JSON object in Groovy

Im Trying to write a Groovy script which performs a REST api call and gets an JSON object, then, i need to get a specific string out of this JSON and check if it matches another string that i provides in the script.
i did everything until the section of comparison,
the string that im getting from the JSON looks like
[AAAAAA/BBBBBB/CCCCCC/file.txt]
and this is my Groovy script:
/*Import Section*/
//--------------//
groovy.json.*
/*Var Declaration*/
//---------------//
String errMessage = "There were no Junit tests impacted in this PR,
Comparison is: "
String scssMessage = "There were Junit tests impacted in this PR,
Comparison is: "
usr= "USERNAME"
pass= "PASSWORD"
pr_num = 92
String validPath = "AAAAAA/BBBBBB/CCCCCC/DDDDDD/EEEEEE"
def copmarison = !false
/*REST API call*/
//------------//
url= "http://{$usr}:
{$pass}#XX.XXX.X.XX:PPPP/rest/api/1.0/projects/XX/repos/TTTTT/pull-
requests/+{$pr_num}/changes?changescope"
process = [ 'bash', '-c', "curl ${url}" ].execute()
process.waitFor()
/*JSON parsing*/
//------------//
def info = new JsonSlurper().parseText(process.text)
def path = info.values.path.toString
/*Impacted JUNIT verifycation*/
//---------------------------//
if(path==validPath){
println ("$scssMessage"+"Valid"+"\n")
comparison=true
}else{
println ("$errMessage"+"Not Valid"+"\n")
comparison=!false
}
Im sure that my comparison isnt good and im looking to compare and find
if part of my "path" contained in my "validPath".
for example, the following case means true:
AAAAAA/BBBBBB/CCCCCC/file.txt
contained in:
AAAAAA/BBBBBB/CCCCCC/DDDDDD/EEEEEE
and i need to find a way to make this comparison
please help
If I understand your question correctly, all you need to check is the path part of your file against a specific path. In that case, this will work:
// you should already have these; including here for clarity
​def file = "AAAAAA/BBBBBB/CCCCCC/file.txt"
def path = "AAAAAA/BBBBBB/CCCCCC/DDDDDD/EEEEEE"
return path.contains(file[0..file.lastIndexOf("/")]​​​)​

What is the best way to check all JSON properties values type?

I'm trying to check in my integration test if all of values from some specific property has the same type. I was trying to do it along with jsonPath and JsonPathResultMatchers but without success. Finally in I did something like this :
MvcResult result = mockMvc.perform(get("/weather/" + existingCity))
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
String responseContent = result.getResponse().getContentAsString();
TypeRef<List<Object>> typeRef = new TypeRef<List<Object>>() {
};
List<Object> humidities = JsonPath.using(configuration).parse(responseContent).read("$.*.humidity", typeRef);
Assertions.assertThat(humidities.stream().allMatch(humidity -> humidity instanceof Integer)).isTrue();
But I wonder if exist some clearer way to do this, can the same result be achieved with JSONPath ? Or AssertJ has some method to find it without usage stream code
Just answering on the AssertJ part: Stream assertions are provided with some caveats as the Stream under test is converted to a List in order to be able to perform multiple assertions (otherwise you can't as a Stream can only be consumed once).
Javadoc: assertThat(BaseStream)
Example:
assertThat(DoubleStream.of(1, 2, 3)).isNotNull()
.contains(1.0, 2.0, 3.0)
.allMatch(Double::isFinite);
I have happily used https://github.com/lukas-krecan/JsonUnit to check JSON, you can give it a try and see if you like it.
I personnaly would rather validate it against a JSON schema. There are Java validator implementations that could help you