How to pass Map between testCases using properties - groovy

I want to do the following in SOAPUI using Groovy:
In a TestCase1 select values (Lastname, firstname) from database, and create a Map with dynamic values: def Map = [Login :"$Login", Nom: "$Nom"]
I need my map to be transferred to another TestCase, for this
I'm trying to put my map into properties:
testRunner.testCase.setPropertyValue( "Map", Map)
But I have error:
groovy.lang.MissingMethodException: No signature of method:
com.eviware.soapui.impl.wsdl.WsdlTestCasePro.setPropertyValue() is
applicable for argument types: (java.lang.String,
java.util.LinkedHashMap) values: [OuvInfoPersoMap,
[Login:dupond0001, Nom:Dupond]] Possible solutions:
setPropertyValue(java.lang.String, java.lang.String),
getPropertyValue(java.lang.String) error at line: 123
I found some posts on internet that suggests to use metaClass groovy property
context.testCase.metaClass.map = Map
log.info context.testCase.map
But I don't think it enough in my case.
I would like to be able to pass a map to Testcase2 using:
createMap = testRunner.testCase.testSuite.project.testSuites.testCases["TestCase1"]
createMap.map
Hopefully you can help me solving this problem.
Thanks advance

As #SiKing correctly explain in the comments, setPropertyValue method expects and String for the property name and for the property value.
Note that as #Rao suggest in general testCase execution should be independent, however despiste this technically it's possible to do what you ask for.
So a possible solution for your case is in the first testCase to serialize the Map to String in order that it's possible to save using setPropertyValue(Strig propertyName, String value) method, and then in the second testCase deserialitze it, something like the follow code must work:
TestCase 1
Serialize the map using inspect() method and save it as a property:
def map = ['foo':'foo','bar':'bar', 'baz':'baz']
testRunner.testCase.setPropertyValue('map',map.inspect())
TestCase2
Deserialitze the String property using Eval.me(String exp)::
// get the first testCase
def testCase1 = testRunner.testCase.testSuite.testCases["TestCase1"]
// get the property
def mapAsStr = testCase1.getPropertyValue('map')
// deserialize the string as map
def map = Eval.me(mapAsStr)
assert map.foo == 'foo'
assert map.bar == 'bar'
assert map.baz == 'baz'

Related

How to access a variable outside of a loop in Groovy

Beginner alert! I have a simple Groovy script that aims to break an argument list into key-value pairs, stored in an associative array (HashMap?). The code works fine until the point where it splits the parameters, but when it tries to put the results back into the array, it throws an exception, stating it cannot access a null element.
I suppose the reason for this is that it can't access the variable that was declared outside the loop.
Here's the script:
def input = "https://weyland-yutani.corp/engineering/bio?param1=1&param2=2"
def params = [:] // wanna store key-value pairs here
if (input.split('\\?').size() >= 2) {
def p = input.split('\\?').last() // get the param string
p.split('\\&').each { // cut the string into an argument list
def keyval = it.split('=') // cut the argument into a key-value pair
println keyval // <-- prints "[param1, 1]", looks okay
params[keyval[0]].put(keyval[1]) // ERROR: "Cannot invoke method put() on null object"
//params[keyval[0]].add(keyval[1]) // ERROR, same sh**
}
}
Error message:
Caught: java.lang.NullPointerException: Cannot invoke method put() on null object
java.lang.NullPointerException: Cannot invoke method put() on null object
at jdoodle$_run_closure1.doCall(jdoodle.groovy:10)
[...]
As it was stated in this article, the way you declare a variable can affect it's scope, but none of my tries succeeded.
Could you give me an advice what am I missing?
The following code:
def input = "https://weyland-yutani.corp/engineering/bio?param1=1&param2=2"
def params = input.tokenize('?').last().tokenize('&').collectEntries { keyval ->
keyval.tokenize('=')
}
println params.getClass()
println params
demonstrates one way of doing this. When run, this prints:
─➤ groovy solution.groovy
class java.util.LinkedHashMap
[param1:1, param2:2]
─➤
As an alternative, if you are ok with using an external library, you could use a url parsing class. This example from HttpBuilder (which is a tad outdated at this point, there are probably others out there):
#Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.2')
import groovyx.net.http.URIBuilder
def input = "https://weyland-yutani.corp/engineering/bio?param1=1&param2=2"
def uri = new URIBuilder(input)
println uri.query.getClass()
println uri.query
which, when run, prints:
─➤ groovy solution2.groovy
class java.util.HashMap
[param1:1, param2:2]
─➤
As another example, this time using google http client library class GenericUrl:
#Grab('com.google.http-client:google-http-client:1.39.1')
import com.google.api.client.http.GenericUrl
def input = "https://weyland-yutani.corp/engineering/bio?param1=1&param2=2"
def url = new GenericUrl(input)
println (url instanceof Map)
url.each { k, v ->
println "$k -> $v"
}
println "value of param1: ${url.param1}"
which, when executed prints:
─➤ groovy solution3.groovy
true
param1 -> [1]
param2 -> [2]
value of param1: [1]
─➤
It should be noted that google does the right thing here. When asking for the value of a parameter, the answer should really be a list. This is because you can say ?a=1&a=2&a=3 which from what I understand should be interpreted not as replacing the value of a, but rather as a being a list of values 1, 2, 3.
So when you ask the google library for the value of a param, you get back a list which in this case happens to be one param long.
There is no code that is ever putting anything in params so when you do params[keyval[0]] that will always evaluate to null, so params[keyval[0]].put(keyval[1]) can't work because you are invoking .put on a null reference.

How to append multiple strings in Groovy?

I am parsing an XML file in Groovy and later I need to append the variables returned.
def lmList = slurperResponse.LastGlobal.HeatMap
String appendedString = lmList.country + lmList.ResponseTime + lmList.timeset
This doesn't work to append the 3 strings. It just assigns the first string to the right. How to properly implement it in Groovy? I tried concat and it threw the following error:
groovy.lang.MissingMethodException: No signature of method: groovy.util.slurpersupport.NodeChildren.concat() is applicable for argument types: (groovy.util.slurpersupport.NodeChildren) values: [4468]
Possible solutions: toFloat(), collect(), collect(groovy.lang.Closure)
at
Yor code shall look like:
String appendedString = "${lmList.country}${lmList.ResponseTime}${lmList.timeset}"
The exception you are getting means, that you are trying to invoke the plus()/concat() method which is not provided by NodeChildren
As an alternative to injecteer -
def lmList = slurperResponse.LastGlobal.HeatMap
String appendedString = lmList.country.toString() + lmList.ResponseTime.toString() + lmList.timeset.toString()
You weren't trying to add strings, you were trying to add nodes the happen to contain strings.
Assuming the xml looks like:
def xml = '''
<Root>
<LastGlobal>
<HeatMap>
<Country>USA</Country>
<ResponseTime>20</ResponseTime>
<TimeSet>10</TimeSet>
</HeatMap>
</LastGlobal>
</Root>
'''
Below should give what is expected:
def slurped = new XmlSlurper().parseText(xml)
assert slurped.LastGlobal.HeatMap.children()*.text().join() == 'USA2010'

Calling groovy method from script

I'm writing a program in groovy, I want it to run a script with dynamically changing variables. The script is supposed to execute a method with its variables. This method is located in the program that runs the script.
The script would contain something like this:
// getAttribute is a method in my main program, the program which also runs the script
value = getValue("java.lang:type=OperatingSystem", "FreePhysicalMemorySize")
// do something with the value
if (value > 9000) { output = "ERROR" }
// the same thing maybe a few more times
value = getValue(...
I want to keep it as simple as possible.
I was working with these examples: http://groovy.codehaus.org/Embedding+Groovy
I already tried to use the GroovyScriptEngine, but it seems like the script only accepts Strings as input values. It would be great if I could hand over method pointers.
Just trying to hand over an integer like this:
def roots = 'PATH\\script.groovy'
def groscreng = new GroovyScriptEngine(roots)
def binding = new Binding()
def input = 42
binding.setVariable("input", input)
groscreng.run("script.groovy", binding)
println binding.getVariable("output")
With this script.groovy
output = ${input}
results in this error:
Caught: groovy.lang.MissingMethodException: No signature of method: script.$() is applicable for argument types: (script$_run_closure1) values: [script$_run_closure1#fcf50]
Possible solutions: is(java.lang.Object), run(), run(), any(), any(groovy.lang.Closure), use([Ljava.lang.Object;)
Receiving the value in the script as a String like "${input}" works just fine.
I know it has to work somehow and I would appreciate any help or other suggestions!
output = ${input}
isn't valid groovy
Try:
output = input

groovy Expando : why it consider the local variable and not the expando properties?

looking at this test code:
def a = "test"
def expando = new Expando()
expando.a = a
expando.foobar = {a}
expando.a = "test1"
assert expando.foobar() != a
why the last assertion fail? it considers "a" as the local variable and not as the expando.a properties.
Thanks for help
Perhaps I am mistaken, but when you invoke expando.foobar(), it returns the result of the closure that was assigned to foobar. In this case, it is a, so it returns the value of a: test.
expando.foobar() does not call the property 'a' because closures do not look for their delegate unless a variable is not defined in scope (and in this case it is).
Edit:
If you were to do expando.foobar = {delegate.a}, that would return the results you are expecting.

Get key in groovy maps

def map = [name:"Gromit", likes:"cheese", id:1234]
I would like to access map in such a way that I can get the key
something like the output should be
map.keys returns array of string. basically i just want to get the keys
output:
name
likes
id
try map.keySet()
and if you want an array:
map.keySet() as String[]; // thx #tim_yates
Or, more groovy-ish:
map.each{
key, value -> print key;
}
Warning: In Jenkins, the groovy-ish example is subtly broken, as it depends on an iterator. Iterators aren't safe in Jenkins Pipeline code unless wrapped in a #NonCPS function.
def map = [name:"Gromit", likes:"cheese", id:1234]
println map*.key
In groovy * is use for iterate all

Resources