How to run twice soap request in SoapUI using threads? - multithreading

In SoapUI I prepared TestCase (Options - generate data) consisting of three test steps:
Properties
Groovy Script
Generate (disabled)
In this test I want to run third step only two times in the same time (that's why I don't use LoadTest) and verify obtained results - they should be different. For this, I wrote a simple script which is presented below.
def testData = testRunner.testCase.getTestStepByName("Properties");
class MyThread extends Thread {
def i;
def testData;
MyThread(def i, def testData) {
this.i = i;
this.testData = testData;
}
void run() {
generateData();
}
void generateData() {
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
def testCaseStep = testRunner.testCase.testSuite.testCases["Options - generate data"];
def soapStep = testCaseStep.testSteps["Generate"];
soapStep.run(testRunner, context);
def xmlResponse = groovyUtils.getXmlHolder("Generate#response")
def responseData = xmlResponse.getNodeValues("//ns2:getResponse/ns2:response");
def row = "row" + this.i;
this.testData.setPropertyValue(row, responseData.toString());
}
}
MyThread thread1 = new MyThread(0, testData);
MyThread thread2 = new MyThread(1, testData);
thread1.start();
thread2.start();
while ((thread1.isAlive() && thread2.isAlive())) {
def data1 = testData.getPropertyValue("row0");
def data2 = testData.getPropertyValue("row1");
assert data1 != data2;
}
Unfortunately this code doesn't work correctly - I don't have any error, but SOAP requests don't start, new variables are not created and assertion is failed.
Could you tell me what is necessary to obtain good result of this test?
I will be very grateful for any help.

Couple of things which are fixed in the code:
context is used in the method and is not available
threads to be joined
while getting the data, you need the object reference
Fixed code:
def testData = context.testCase.getTestStepByName("Properties")
class MyThread extends Thread {
def threadId
def testData
def context
MyThread(def i, def testData, def context) {
threadId = i
this.testData = testData
this.context = context
}
void run() {
generateData()
}
void generateData() {
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def soapStep = context.testCase.testSteps["Generate"]
soapStep.run(context.testRunner, context)
def xmlResponse = groovyUtils.getXmlHolder("Generate#response")
def responseData = xmlResponse.getNodeValues("//ns2:getResponse/ns2:response")
testData.setPropertyValue("row${threadId}" as String, responseData.toString())
}
}
MyThread thread1 = new MyThread(0, testData, context)
MyThread thread2 = new MyThread(1, testData, context)
thread1.start()
thread1.join()
thread2.start()
thread2.join()
while ((thread1.isAlive() && thread2.isAlive())) {
def data1 = thread1.testData.getPropertyValue(thread1.threadId)
def data2 = thread2.testData.getPropertyValue(thread2.threadId)
assert data1 != data2
}

Related

groovy - replace values in json when loading from jmx

I have a piece a code as below. This is loading data from JMX to monitoring tool. Unfortunately, there are some 'NaN' values, which are not read properly by monitoring tool, and this interrupts transfer. My intention is to replace 'on fly' values 'NaN' to 'null'.
Has anybody any idea how to do it?
BR
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import java.security.PrivilegedAction;
def hostName = hostProps.get("system.hostname")
def jmxPort = "10002"
def query = "Hadoop:service=hiveserver2,name=hiveserver2"
def metricsURL = "http://${hostName}:${jmxPort}/jmx?qry=${query}"
def ad = true
public class FetchMetrics implements PrivilegedAction {
def url;
public FetchMetrics(String url) {
this.url = url;
}
public Object run() {
URL urlObject = new URL(url);
def con = (HttpURLConnection) urlObject.openConnection();
return con.getInputStream();
}
}
lc = new LoginContext("Client");
lc.login();
Subject subject = lc.getSubject();
PrivilegedAction action = new FetchMetrics(metricsURL);
def metrics = Subject.doAsPrivileged(subject, action, null);
def jsonSlurper = new JsonSlurper()
def deviceMetrics = jsonSlurper.parse(metrics)
// Hit out endpoint and get our metrics
//deviceMetrics = jsonSlurper.parse(new URL(metricsURL))
deviceMetrics.'beans'[0].each {
println it
}
return 0
simplest way to use LAX json slurper, however it will parse NaN as a string "NaN"...
import groovy.json.JsonSlurper
import groovy.json.JsonParserType
import groovy.json.JsonBuilder
def jsonSlurper = new JsonSlurper().setType( JsonParserType.LAX )
def json = jsonSlurper.parseText('{ "a":111, "b": NaN}')
println new JsonBuilder(json).toPrettyString()
prints
{
"a": 111,
"b": "NaN"
}

How to run SoapUI teststeps in parrallel with Groovy

SoapUI has options to run your test-suites and test-cases in parallel but no such thing for doing it with test-steps.
How can I achieve such a thing with a Groovy teststep inside my testcase?
This is my current code:
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner
//Get all Soap type test steps within the testCases
for ( testStep in testRunner.testCase.getTestStepsOfType(com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep.class)){
//Print out the name for the testStep
tsname = testStep.getName();
log.info tsname;
//thread = new Thread("$tsname")
def th = new Thread("$tsname") {
#Override
public void run(){
//Set the TestRunner to the respective TestCase
TestRunner = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner(testRunner.testCase, null);
//Run them all and then rejoin the threads
log.info("thread: " + tsname)
TestRunner.runTestStepByName(tsname);
def soapResponse = TestRunner.getTestCase().getTestStepByName(tsname).getProperty("Response");
log.info "soapResponse: " + soapResponse;
th.join();
}
}
th.start();
th.join();
}
Managed to fix it myself and posted the answer here for all who stumble into the same problem:
import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep
List<String> steps = testRunner.testCase.getTestStepsOfType(com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep.class)
def map = [:]
//define the threads list, this will hold all threads
def threads = []
def kickEm = steps.each{ step ->
def th = new Thread({
stepName = step.getName();
log.info "Thread in start: " + step.getName();
//Set the TestRunner to the respective TestCase
TestRunner = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner(testRunner.testCase, null);
//Run the corresponding teststep
TestRunner.runTestStepByName(step.getName());
//Get the response of the current step
def soapResponse = context.expand(TestRunner.getTestCase().getTestStepByName(step.getName()).getPropertyValue('Response')) as String;
log.info "In thread "+step.getName()+" soapResponse: " + soapResponse
//Put this into a map, the key is the stepname and the value is its response, so we can retrieve it all outside the each loop
map.put(step.getName(), soapResponse);
})
log.info "Putting new Thread({..}) th back into the threads list";
threads << th;
}
threads.each { it.start(); }
threads.each { it.join(); }
log.info "Map: "
map.each { step, response ->
log.info "Step: ${step} has the response ${response}"
};
log.info "Done!"

Print the specific field from list

Please help to print the assetNumber. Need to search for specific assetname and print its associated assetNumber using list in groovy.
Currently, it does not print value. It struck once search criteria is entered.
class Main
{
public static void main(String[] args)
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in))
List list = new ArrayList()
Asset asset = new Asset()
def name
def assetNumber
def assigneeName
def assignedDate
def assetType
String userInput = "Yes"
while(userInput.equalsIgnoreCase("Yes"))
{
println "Enter the asset details:"
asset.name = br.readLine()
asset.assetNumber= Integer.parseInt(br.readLine())
asset.assigneeName = br.readLine()
asset.assignedDate = Date.parse('dd/MM/yyyy', br.readLine())
list.add(asset)
println "Do you want to continue(yes/no)"
userInput = br.readLine()
}
println "Enter the asset type:"
assetType = br.readLine()
println "Asserts with type "+assetType+":"
def items = list.findAll{p->p.name == assetType }
items.each { println it.assetNumber }
}
}
class Asset
{
def name
def assetNumber
def assigneeName
def assignedDate
}
You are overwriting the value in your Asset object, then adding the same object to the list every time
If you create a new asset inside the loop (rather than outside it), it should work...
Something like this:
import groovy.transform.*
class Main {
static main(args) {
def console = System.console()
def list = []
while (true) {
def name = console.readLine 'Enter the asset name:'
def number = console.readLine 'Enter the asset number:'
def assignee = console.readLine 'Assignee name:'
def date = console.readLine 'Date (dd/MM/yyyy):'
list << new Asset(
name: name,
assetNumber: Integer.parseInt(number),
assigneeName: assignee,
assignedDate: Date.parse('dd/MM/yyyy', date)
)
if ('Y' != console.readLine('Enter another (y/n):')?.take(1)?.toUpperCase()) {
break
}
}
def type = console.readLine 'Enter the asset type:'
println "Assets with type $type:"
list.findAll { p -> p.name == type }
.each { println it.assetNumber }
}
#Canonical
static class Asset {
def name
def assetNumber
def assigneeName
def assignedDate
}
}

Loop with groovy to execute a TestCase in soapui

i wanto run 5 times a testcase in soapui using groovy.
i found the following code in Stackoverflow and added the loop part but it executes randomly.
Sometimes it executes 2 times and sometimes 4 times.
here is the code:
def a = 5;
while (a>0) {
a--;
def testCase = testRunner.testCase.testSuite.testCases["TestCase"];
def properties = new com.eviware.soapui.support.types.StringToObjectMap();
def async = false;
testCase.run(properties, async);
}
Thank you
def doSomething() {
println 'Foo Bar'
}
5.times {
doSomething()
}
First thing, you do not want to def testCase in your script, as testCase is usually defined for you.
def myTestCase = testSuite.getTestCaseByName("some TestCase")
def myContext = (com.eviware.soapui.support.types.StringToObjectMap)context
5.times {
myTestCase.run(myContext, false)
}
You also did not specify where you are doing this from. The above code will work from test suite Setup Script. If you are doing it elsewhere, you will probably need to adjust def myTestCase.
I have following script in Setup Script of a test Suite and it is running indefinite loop:
def count=context.expand('${#Global#run}')
log.info count
def project1 = runner.testCase.testSuite.project
def properties = new com.eviware.soapui.support.types.StringToObjectMap()
def testcase = project1.getTestSuiteByName("TestSuite 1").getTestCaseByName("Login");
def testcase1 = project1.getTestSuiteByName("TestSuite 1").getTestCaseByName("Logout");
// This will run everything in the selected project
for(int i=1;i<=count;i++){
// testRunner = testcase.run(new com.eviware.soapui.support.types.StringToObjectMap(), false)
def myContext = (com.eviware.soapui.support.types.StringToObjectMap)context
testcase.run(myContext, false)
sleep(70000)
//testRunner = testcase1.run(new com.eviware.soapui.support.types.StringToObjectMap(), false)
testcase1.run(myContext, false)
sleep(5000)
log.info( "Finished running "+i+" cycle" )
if(i==count){
testRunner.cancel('Test Execution is completed')
break;
}
}

How to add a new closure to a class in groovy

From Snipplr
Ok here is the script code, in the comments is the question and the exception thrown
class Class1 {
def closure = {
println this.class.name
println delegate.class.name
def nestedClos = {
println owner.class.name
}
nestedClos()
}
}
def clos = new Class1().closure
clos.delegate = this
clos()
//Now I want to add a new closure to Class1
def newClosure = {
println "new Closure"
println this.class.name
println delegate.class.name
def nestedClos = {
println owner.class.name
}
nestedClos()
}
//getAbc to create a property, not a method
Class1.metaClass.getAbc = newClosure
//What happens here is that the property abc is not used as a closure per se, it's used
//as a property and when I execute it just run the closure and when I want to change
//the delegate, a null pointer is thrown
clos = new Class1().abc //abc executed instead of passing the reference closure
clos.delegate = this //Exception!!!!
clos()
Ok, It's done it's not a fancy way, but I have the solution....yeah!
Create the property as object and later assign the closure
class Class1 {
def closure = {
println this.class.name
println delegate.class.name
def nestedClos = {
println owner.class.name
}
nestedClos()
}
}
def clos = new Class1().closure
clos.delegate = this
clos()
//Now I want to add a new closure to Class1
def newClosure = {
println "new Closure"
println this.class.name
println delegate.class.name
def nestedClos = {
println owner.class.name
}
nestedClos()
}
//before edit
//Class1.metaClass.abc = new Object()
Class1.metaClass.abc = newClosure
def cl = new Class1()
//Before edit
//For the sake of simplicity we are going to use & for the method
//clos = cl.abc
closs = cl.&abc
clos.delegate = this
clos()

Resources