Error in JMeter PreProcessor and PostProcessor - groovy

I am using JMeter to run query load tests against an Elasticsearch cluster. I have a csv file of 100 names that I am iterating through to populate the ES query with a different search term on each call.
The column in the csv file is called name, so in the JMeter HTTP request, the query in the Body Data looks like this:
{
"query": {
"match": {
"search_name": "${name}"
}
}
}
And to iterate through the csv file to get the names, I have a JSR223 PreProcessor as a child of the HTTP request as such:
upto(1, {
if (vars.get('param' + "$it") != null) {
sampler.addArgument(vars.get('param' + "$it"),'name')
}
})
then a JSR223 PostProcessor as such:
upto(1, {
vars.remove("param" + "$it")
})
I came up with this approach by reading the accepted answer at this thread: How to make the search parameters in http request as dynamic in jmeter and adjusting as I saw fit.
The processing code is doing what it's supposed to be doing as far as correctly populating the queries, and all HTTP Requests are successful. However, every call is also throwing an error in the Jmeter log at both the PreProcessor and PostProcessor step:
ERROR o.a.j.m.JSR223PreProcessor: Problem in JSR223 script, JSR223 PreProcessor
javax.script.ScriptException: groovy.lang.MissingMethodException: No signature of method: org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.upto() is applicable for argument types: (Integer, Script1$_run_closure1) values: [1, Script1$_run_closure1#7c7ff704]
Possible solutions: put(java.lang.String, java.lang.Object), wait(), grep(), any(), dump(), find()
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:320) ~[groovy-jsr223-3.0.11.jar:3.0.11]
at org.codehaus.groovy.jsr223.GroovyCompiledScript.eval(GroovyCompiledScript.java:71) ~[groovy-jsr223-3.0.11.jar:3.0.11]
at javax.script.CompiledScript.eval(CompiledScript.java:93) ~[java.scripting:?]
at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:217) ~[ApacheJMeter_core.jar:5.5]
at org.apache.jmeter.modifiers.JSR223PreProcessor.process(JSR223PreProcessor.java:45) ~[ApacheJMeter_components.jar:5.5]
at org.apache.jmeter.threads.JMeterThread.runPreProcessors(JMeterThread.java:978) ~[ApacheJMeter_core.jar:5.5]
at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:561) ~[ApacheJMeter_core.jar:5.5]
at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:501) ~[ApacheJMeter_core.jar:5.5]
at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:268) ~[ApacheJMeter_core.jar:5.5]
at java.lang.Thread.run(Thread.java:833) ~[?:?]
Caused by: groovy.lang.MissingMethodException: No signature of method: org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.upto() is applicable for argument types: (Integer, Script1$_run_closure1) values: [1, Script1$_run_closure1#7c7ff704]
Possible solutions: put(java.lang.String, java.lang.Object), wait(), grep(), any(), dump(), find()
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.callGlobal(GroovyScriptEngineImpl.java:404) ~[groovy-jsr223-3.0.11.jar:3.0.11]
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.access$100(GroovyScriptEngineImpl.java:90) ~[groovy-jsr223-3.0.11.jar:3.0.11]
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl$3.invokeMethod(GroovyScriptEngineImpl.java:303) ~[groovy-jsr223-3.0.11.jar:3.0.11]
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:73) ~[groovy-3.0.11.jar:3.0.11]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:51) ~[groovy-3.0.11.jar:3.0.11]
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:83) ~[groovy-3.0.11.jar:3.0.11]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:194) ~[groovy-3.0.11.jar:3.0.11]
at Script1.run(Script1.groovy:1) ~[?:?]
at org.codehaus.groovy.jsr223.GroovyScrip
tEngineImpl.eval(GroovyScriptEngineImpl.java:317) ~[groovy-jsr223-3.0.11.jar:3.0.11]
In the interest of saving space, I won't paste the PostProcessor code, which is virtually identical.
I am not well-versed in groovy at all, and again, I did my best to adapt the pre and post processor code from the other thread. Even though everything appears to be working, I'd like to resolve this error b/c I can't imagine I have a clean test going with all these errors thrown.

The error you're getting means syntax error, you cannot call upto() function per se, according to its JavaDoc:
Iterates from this number up to the given number, inclusive, incrementing by one each time.
So I think you need to amend it to look like:
0.upto(1, {
if (vars.get('param' + "$it") != null) {
sampler.addArgument(vars.get('param' + "$it"),'name')
}
})
the Post-Processor can be just removed.
More information on Groovy scripting in JMeter: Apache Groovy: What Is Groovy Used For?
Groovy has its own very comprehensive documentation: https://groovy-lang.org/documentation.html#gettingstarted

Related

JSR223 PostProcessor error logs due to same json path in previous multiple response model

I have seen below error in the logs in JSR223 PostProcessor despite the script running successfully and the Jmeter steps having no issues.
Caused by: java.lang.NullPointerException: Cannot get property 'result' on null object
My JSR223 PostProcessor - groovy 3.0.7 script looks like this:
import groovy.json.JsonSlurper;
String json = prev.getResponseDataAsString();
def root = new JsonSlurper().parseText(json);
def C_accountNumber = root.myAccount.result[0].accountNumber;
vars.put("C_accountNumber", C_accountNumber);
The response just above the above script
{
"myAccount": {
"result": [
{
"accountNumber": "Something",
"accountAddress": "Something",
}
]
}
}
However, the thing I noticed was, well before the above script in multiple previous step responses also I see below path. (exactly same path myAccount.result[0] )
So I am guessing this caused the issue because as one of the previous responses, I can't see accountNumber despite having myAccount.result[0].
e.g.
{
"myAccount": {
"result": [
{
"country": "Something",
"address": "Something",
}
]
}
}
Because this part String json = prev.getResponseDataAsString(); in the groovy script go through all the previous responses but NOT just immediate before. Is my understanding correct?
Is there way to get rid of these errors in the log?
Your post processor should be defined as a child of the HTTP request
JMeter Post-Processor is execute in scope, for specific HTTP request add it as a child of the request
Post-Processor executes some action after a Sampler Request has been made. If a Post-Processor is attached to a Sampler element, then it will execute just after that sampler element runs.
Be aware of JMeter Scoping Rules
If you put the PostProcessor at the same level as several Samplers - it will be applied to all of them
So if you want to execute the PostProcessor after a certain sampler only - you need to make the PostProcessor a child of the particular Sampler:

How do I parameterize groovy statement in RestAssured body() method

I'm trying to write a parameterized test using a csv file as the data source. I would like to check the json node for a number if keys, if the are present. Here my first attempt:
#ParameterizedTest(name = "{index} => name={0}")
#CsvFileSource(resources = "fields.csv", numLinesToSkip = 0)
void verifyFields(String name) {
Response response = getResponse(); // rest - assured query response
response
.then()
.assertThat()
.body("components.any { it.containsKey('" + name + "') }", is(true));
But I keep getting the following error when trying to verify that the key xzy is present:
Caused by: groovy.lang.MissingMethodException: No signature of method: java.util.HashMap$Node.containsKey() is applicable for argument types: (String) values: [xyz]
I'm not sure I'm using the groovy statement correctly. I'm just trying to use the parameters from the file.

how can i add js to geb locator?

After this code I have error:
gebLocator(wait: true) { $("a#fCoverage") }
browser.js.exec(gebLocator+ ".addEventListener('click', function(){alert('GTM')});")
Error message:
groovy.lang.MissingMethodException: No signature of method:
geb.navigator.NonEmptyNavigator.plus() is applicable for argument
types: (java.lang.String) values: [.addEventListener('click',
function(){alert('GTM')});] Possible solutions:
plus(geb.navigator.Navigator), has(java.lang.String),
is(java.lang.String), last(), value(), add(java.lang.String)
The error message means that you have tried to execute method plus(String) on NonEmptyNavigator what is impossible because NonEmptyNavigator doesn't have such a method.
If you want to execute js code using geb driver:
browser.js.exec("document.getElementById('fCoverage').addEventListener('click', function(){alert('GTM')});")

Access methods defined in another groovy script

I have two groovy scripts A and B.
A looks like:
import some.Class
//Some helper function
String doSomeWork(Integer input) {
//does something with input and returns a String
return "result: $input"
}
//Now do some real stuff here
println( doSomeWork(42) )
In B I want to import A (its in the classpath) and use its doSomeWork:
import A
println A //prints class A. This means we can access it here. =)
println( A.doSomeWork(45) ) //Now try to call As doSomeWork
The last line however results in an exception:
Caught: groovy.lang.MissingMethodException: No signature of method: static A.doSomeWork() is applicable for argument types: (java.lang.Integer) values: [45]
Possible solutions: doSomeWork(java.lang.Integer)
groovy.lang.MissingMethodException: No signature of method: static A.doSomeWork() is applicable for argument types: (java.lang.Integer) values: [45]
Possible solutions: doSomeWork(java.lang.Integer)
at B.run(B.groovy:3)
import A //Will execute As code
println A //prints class A. This means we can access it here. =)
println( (new A()).doSomeWork(45) ) //Now call As doSomeWork
What do I have to do to successfull call As doSomeWork in script B?
EDIT: Okay, I found out. it is not a static method but a method of A. So (new A()).doSomeWork(45) is doing the job. However, that means when A is imported, all its code is executed before Bs code. How can I avoid that? My goal is to only use As method (which obvioulsy does not access any of As properties) without A doing any other side effects.

Can't pass closures in groovy

I am trying to run a basic example for the Geb library (http://www.gebish.org/manual/current/intro.html#introduction). Here is the code:
import geb.Browser
Browser.drive {
go "http://google.com/ncr"
// make sure we actually got to the page
assert title == "Google"
// enter wikipedia into the search field
$("input", name: "q").value("wikipedia")
// wait for the change to results page to happen
// (google updates the page dynamically without a new request)
waitFor { title.endsWith("Google Search") }
// is the first link to wikipedia?
def firstLink = $("li.g", 0).find("a.l")
assert firstLink.text() == "Wikipedia"
// click the link
firstLink.click()
// wait for Google's javascript to redirect to Wikipedia
waitFor { title == "Wikipedia" }
}
When I try to run this (using Eclipse's groovy support) I get the following exception:
Caught: groovy.lang.MissingMethodException: No signature of method: static geb.Browser.drive() is applicable for argument types: (ExampleScript$_run_closure1) values: [ExampleScript$_run_closure1#2a62610b]
Possible solutions: drive(groovy.lang.Closure), drive(geb.Browser, groovy.lang.Closure), drive(geb.Configuration, groovy.lang.Closure), drive(java.util.Map, groovy.lang.Closure), print(java.lang.Object), print(java.io.PrintWriter)
groovy.lang.MissingMethodException: No signature of method: static geb.Browser.drive() is applicable for argument types: (ExampleScript$_run_closure1) values: [ExampleScript$_run_closure1#2a62610b]
Possible solutions: drive(groovy.lang.Closure), drive(geb.Browser, groovy.lang.Closure), drive(geb.Configuration, groovy.lang.Closure), drive(java.util.Map, groovy.lang.Closure), print(java.lang.Object), print(java.io.PrintWriter)
at ExampleScript.run(ExampleScript.groovy:21)
I think this is saying that the closure I am passing to the static Browser.drive method is not type compatible with groovy.lang.Closure, but I don't know why. Simple groovy hello world scripts work fine but passing a closure to a method always returns a similar error.
Plagiarized from: http://groovy.codehaus.org/Differences+from+Java
Java programmers are used to semicolons terminating statements and not having closures. Also there are instance initializers in class definitions. So you might see something like:
class Trial {
private final Thing thing = new Thing ( ) ;
{ thing.doSomething ( ) ; }
}
Many Groovy programmers eschew the use of semicolons as distracting and redundant (though others use them all the time - it's a matter of coding style). A situation that leads to difficulties is writing the above in Groovy as:
class Trial {
private final thing = new Thing ( )
{ thing.doSomething ( ) }
}
This will throw a MissingMethodException!

Resources