java.lang.NullPointerException displayed when run testcase inside Groovy Script step - groovy

I am trying to run TestCase from Groovy Script TestStep using Groovy in SoapUI.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context );
def testCase = testRunner.testCase;
def testStep = testCase.testSteps["CreateMeeting"];
testRunner = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner(testCase, null);
testStepContext = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext(testStep);
testStep.run(testRunner, testStepContext);
Error displayed :
java.lang.NullPointerException
Error occured at line :
testStepContext = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext(testStep);
Project Structure :

When you invoke a Groovy test step you get a number of variables pre-declared such as log, context, and testRunner, so you don't have to declare your own.
This worked for me:
//def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context );
def testCase = testRunner.testCase.testSuite.project.getTestSuiteByName("AddBooking").getTestCaseByName("CreateMeeting")
//def testStep = testCase.testSteps["CreateMeeting"]
//testRunner = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner(testCase, null);
//testStepContext = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext(testStep);
def properties = new com.eviware.soapui.support.types.StringToObjectMap ()
testCase.run(properties, false)

Related

Groovy access script variable from application

Need to access the variable defined in the groovy script file
Before executing the script using GroovyShell
However, I am getting error:
groovy.lang.MissingPropertyException: No such property: _THREADS for class: Test1
//Test1.groovy
_THREADS=10;
println("Hello from the script test ")
//scriptRunner.groovy
File scriptFile = new File("Test1.groovy");
def sharedData = new Binding()
def shell = new GroovyShell(sharedData)
def script = shell.parse (scriptFile);
def thread = script.getProperty('_THREADS'); // getting ERROR --
// No such property: _THREADS for class: Test1
//-------
//now run the threads
script.run()
you have to run script before getting property/binding
def sharedData = new Binding()
def shell = new GroovyShell(sharedData)
def script = shell.parse (''' _THREADS=10 ''')
script.run()
println script.getProperty('_THREADS')
try to open AST Browser (Ctrl+T) in groovy console for this code:
_THREADS=10
and you'll see approximately following generated class:
public class script1663101205410 extends groovy.lang.Script {
public java.lang.Object run() {
_THREADS = 10
}
}
where _THREADS = 10 assigns property into binding
however it's possible to define _THREADS as a function then it will be accessible without running script.
def sharedData = new Binding()
def shell = new GroovyShell(sharedData)
def script = shell.parse (''' def get_THREADS(){ 11 } ''')
println script.getProperty('_THREADS')
got the solution using #Field modifier value can be accessed after parsing
import groovy.transform.Field
#Field _THREADS=10
File scriptFile = new File("Test1.groovy");
def sharedData = new Binding()
def shell = new GroovyShell(sharedData)
def script = shell.parse (scriptFile);
def thread = script.getProperty('_THREADS'); //value is accessible

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!"

load external jar in groovy script in SoapUI

I need to call a method inside Jar from groovy script inside SoapUI project.
Due to the lack of administrative access I can't place that jar in "../bin/ext" folder in SaopUI intall directory.
So the only option left is load the jar in runtime and call the method. Very simple approach.
I tried the below approach.
this.class.classLoader.rootLoader.addURL(new URL("file:///H://Foo-2//Foo.jar"));
def cls = Class.forName("test").newInstance();
cls.add()
This is not working as rootLoader is null.
second approach .
def classLoader = ClassLoader.systemClassLoader
def newClassLoader = new URLClassLoader([new File("file:///H://Foo-2//Foo.jar")
.toString().toURL()] as URL[], classLoader)
def cls = Class.forName("test").newInstance();
this is not working too , it's giving me ClassNotFoundException.
I spent a day in this. even change the class name to lower case after seeing this thread.
Edit 1
I tried this too. and change my code like this.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def classpathHacker = new com.eviware.soapui.support.ClasspathHacker ()
log.info "utils=" + groovyUtils
mystring = "file://H://Baz.jar"
com.eviware.soapui.support.ClasspathHacker.addURL( new URL(mystring) )
def cls = new bar() // how to call the static method add of `bar` class ?
log.info cls
My Jar code is too simple. Here it is
public class bar {
public static void main(String[] args) {
add();
}
public static void add(){
String path = "H:" + File.separator + "Groovy" + File.separator + "hi.txt";
File f = new File(path);
f.getParentFile().mkdirs();
try {
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
What all the other option I have? What i am doing wrong?
Solved. Here is the final Groovy script.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def classpathHacker = new com.eviware.soapui.support.ClasspathHacker ()
path = groovyUtils.getProjectPath()
myfile = new java.io.File(path + "/Baz.jar")
mystring = "file://" + path + "/Baz.jar"
log.info "myfile=" + myfile
classpathHacker.addFile( myfile )
com.eviware.soapui.support.ClasspathHacker.addFile( myfile )
com.eviware.soapui.support.ClasspathHacker.addURL( new URL(mystring) )
//import Baz
def instance = this.class.classLoader.loadClass( 'bar', true, false )?.newInstance()
instance.add();
Do you know about com.eviware.soapui.support.ClasspathHacker?
Maybe that is away to go about it, if you really cannot put it to the /ext folder.
Reference:
https://community.smartbear.com/t5/SoapUI-Open-Source/Soapui-is-not-loading-external-jar-file-location-added-to/td-p/7619
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def classpathHacker = new com.eviware.soapui.support.ClasspathHacker ()
log.info "utils=" + groovyUtils
path = groovyUtils.getProjectPath()
myfile = new java.io.File(path + "/ojdbc14.jar")
mystring = "file://" + path + "/ojdbc14.jar"
log.info "myfile=" + myfile
classpathHacker.addFile( myfile )
com.eviware.soapui.support.ClasspathHacker.addFile( myfile )
com.eviware.soapui.support.ClasspathHacker.addURL( new URL(mystring) )
import groovy.sql.*
def sql = groovy.sql.Sql.newInstance( db, userid, password, 'oracle.jdbc.driver.OracleDriver' )

Running specific test step in SoapUI based on testSuite property

I am new to scripting and could use some help. I have an issues regarding SoapUI groovy script I could use help with.
I need a script that will let me run specific testStep in testCase based on value of testSuite property ('CC1' is name of property) with 5 possibilities. I guess switch/case could be used, but don't know how to write it properly.
At the moment I tried using this:
def CC1 = testRunner.testCase.testSuite.getPropertyValue("CC1")
log.info testRunner.testCase.testSuite.getPropertyValue("CC1")
switch(CC1)
{
case ~/^[H1]+$/: testRunner.runTestStepByName( "PT02_H1" ); break;
case ~/^[Y5]+$/: testRunner.runTestStepByName( "PT02_Y5" ); break;
case ~/^[Q2]+$/: testRunner.runTestStepByName( "PT02_Q2" ); break;
case ~/^[T5]+$/: testRunner.runTestStepByName( "PT02_T5" ); break;
default : testRunner.runTestStepByName( "PT02_AQ" );
}
But doesn't run the desired step.
Can someone help me with this please?
Try the following script (run from groovyTestStep):
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context );
def testCase = testRunner.testCase;
def testStep = null;
def CC1 = testRunner.testCase.testSuite.getPropertyValue("CC1")
log.info testRunner.testCase.testSuite.getPropertyValue("CC1")
switch(CC1)
{
case ~/^[H1]+$/: testStep = testCase.getTestStepByName( "PT02_H1" ); break;
case ~/^[Y5]+$/: testStep = testCase.getTestStepByName( "PT02_Y5" ); break;
case ~/^[Q2]+$/: testStep = testCase.getTestStepByName( "PT02_Q2" ); break;
case ~/^[T5]+$/: testStep = testCase.getTestStepByName( "PT02_T5" ); break;
default : testStep = testCase.getTestStepByName( "PT02_AQ" );
}
testRunner = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner(testCase, null);
testStepContext = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext(testStep);
testStep.run(testRunner, testStepContext);
log.info "TEST OK:"+testStep.getName();

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;
}
}

Resources