Eexecute groovy code in soapui cucumber project - groovy

I am trying to run existing SoapUI tests with Cucumber for a customer.
I have use this example https://www.soapui.org/docs/test-automation/junit/junit-integration/
The test execution in Cucumber works fine for SoapUI test cases with REST Requests.
But my customer also uses groovy code in a few test cases. All test cases with groovy code shows in result (test runner) an error.
My question: Is it possible to execute groovy code via Cucumber/JUnit?
I'm not sure in the documentation i haven't found anything about it.
This is my groovy code:
def ec00Configuration = testRunner.testCase.getTestStepByName("Configuration")
def response = new JsonSlurper().parseText(context.expand( '${Request#Response}' )).message
def dealerId = response.find{it.name == ec00Configuration.getPropertyValue("dealerName")}?.id
log.info "Id of dealer is : ${dealerId}"
// move to property for demo!
testRunner.testCase.testSuite.setPropertyValue("dealerId",dealerId)

Related

Run generic groovy script assertion in SoapUI

Is it possible to / how do you run a groovy script from a SoapUI assertion without copy/pasting the script into all of your test steps where you need the same script executed? Is it possible to write a script outside of the assertion and run the script like you are calling a method? So that you can reuse the assertion script in multiple test steps.
So far, I've tried to call a groovy test step from within the assertion, but the run() method requires a testRunner variable which is unavailable from within the assertion. I've also tried to write a groovy script as a subsequent test step (not an assertion) that calls another groovy test step script, but I was unable to transfer the response from one test step to the next (Honestly, I'd rather not create test steps that are really just assertions).
Note: this is not a duplicate of How to create variables in soapui test case that can be accessed across all test steps - groovy test step & script assertion test step? because that question pertains to storing properties, not reusing scripts.
I was able to finally figure out my 2nd approach: add another groovy script as a subsequent test step that has assertions and passes the response. The script is:
context.response = context.expand('${MyTestStep#Response}') // store response to context variable
Object result = testRunner.testCase.testSuite.testCases['Validate Response'].testSteps['Validate Response'].run(testRunner, context)
if(result.getError() != null) {
log.error("error", result.getError())
assert false
}
assert true
MyTestStep is the test step before the groovy script. Validate Response is the name of the test case of the groovy script which is also called Validate Response and is executed via the run method.

using groovy script to validate assertions in robot framework when executing soap test by using suds library

In my soapui test I have written a groovy script to validate all the assertions.I want to do the same in robot framework .
I am executing soapui test from robot framework using suds library.
How can I use my groovy script in Robot framework to verify all the assertions in single go like we do in SOAPUI.
please help
Thanks
You can do your verification in Groovy, but its not very simple. If your verifications are all on the XML and not things like headers or status codes, you can take the XML response from SudsLibrary and pass it to a user library. I did all the tasks to make this work manually, but if you use Maven and the plugins for Groovy and Robot Framework, it would be easier to work with.
The user library must be compiled to a .class file using the compiler, groovyc. Here you can use the SoapUI helper classes you are familiar with. They need to be on the class path when compiling. From the SoapUI installation folder, I added bin\soapui-5.2.0.jar and lib\* to the class path. For Robot Framework to use your Groovy script, classes and public methods must be used per the test library API.
package com.example.soapui;
import com.eviware.soapui.support.XmlHolder
public class Verifications {
public void checkResponse(String xml) {
def holder = new XmlHolder(xml)
holder.namespaces["ns1"] = "http://www.webserviceX.NET"
def average = holder.getNodeValue("//ns1:Average[1]")
assert average == "2.5"
}
}
Here is a simple test that calls a public web service and invokes the Groovy script to check the response.
*** Settings ***
Library SudsLibrary
Library Collections
Library com.example.soapui.Verifications
*** Test Cases ***
Simple
Create Soap Client http://www.webservicex.net/Statistics.asmx?WSDL
Set Return Xml True # soap calls from now one will return XML
${dbl array}= Create Wsdl Object ArrayOfDouble
Append To List ${dbl array.double} 2.0
Append To List ${dbl array.double} 3.0
${result}= Call Soap Method GetStatistics ${dbl array}
Check Response ${result} # pass the XML to the user keyword written in Groovy
During execution, both Groovy and SoapUI jar files need to be on the class path.
C:\ws\groovy>jybot groovy.robot
==============================================================================
Groovy
==============================================================================
Simple | PASS |
------------------------------------------------------------------------------
Groovy | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
==============================================================================
Output: C:\ws\groovy\output.xml
Log: C:\ws\groovy\log.html
Report: C:\ws\groovy\report.html

Creating script library in SoapUI free version

I am new in SoapUI and groovy scripting
I would like to create a repository of groovy scripts that can be reused at various test steps
I am using SoapUI Free version and following is the structure of my SoapUI Project
Project
|-TestSuite
| |-TestCase
| |-TestSteps
| |-LocalScript (Groovy TestStep to reuse library scripts)
| |-OtherTestStep (Run TestCase TestStep)
|-ScriptLibrary
|-TestCase
|-TestSteps
|-GroovyScriptStep1 (Contain a class for commonly used functions)
|-GroovyScriptStep2 (Contain another class for other functions)
Here is what I was able to do:
I was able to create a library using the sample mentioned in this post. Similar to example in the post, my code in test step (GroovyScriptStep1 as per above structure) of library was just reading some value from external file and is used in test step of other TestSuite (LocalScript step in above structure).
Here is the problem:
Now I want to create a new class and add a function to it which will need info from running class and simply print it. The difference here is that some values are generated in the test run and should be passed to library script inorder to process/print etc.
To make my question more clear following is the code snippet
I will be using a simple scenario here
Sample objective: Want to be able to print all the assertions and status (since this will be used in all the test cases I want to create a library)
Code for same when not using library will be as under(this can go as groovy script step)
def obj = context.testCase.getTestStepByName("Request 1");
def assertions = obj.getAssertionList()
//Loop on assertions
assertions.each{
log.info(it.name + ' --> ' + it.status)
Code something similar in Library TestSuite's Test case step
context.setProperty("Assertions", new Assertions());
class Assertions{
def printAssertion(def someArgumentToGetAssertionlistforTestStepinAnotherTestSuite){
def obj = ????
def assertions = obj.getAssertionList()
//Loop on assertions
assertions.each{
log.info(it.name + ' --> ' + it.status)
}
}
}
Code from where I want to call this method (LocalScript as per above project structure)
scripts = testRunner.testCase.testSuite.project.testSuites["ScriptLibrary"];
scripts.testCases["Scripts"].testSteps["Assertions"].run(testRunner, context);
context.Assertions.printAssertion(ArgumentRequired);
This is just one example, I want to create libraries of some more common scripts that use context variable when used locally
Kindly help me with this and please let me know if some more information/clarification is required
What I get from your questions is that you want to create a code library in SoapUI that can be reused.
I think the best way is by creating jar files and deploying it in ext folder of SoapUI
Create a new groovy script file with a class (follows java standards in file naming i.e. class name and file name should be same)
Compile the groovy code file
Create the jar file
Deploy the jar file at SoapUI_Home/bin/ext folder
Restart the SoapUI if was already open
Create the object of class and use the methods anywhere in the SoapUI projects
Note: If you are migrating your project to some other machine, make sure to migrate these libraries as well if you are using them in projects
Details with example:
Step 1: Create a new groovy script file with a class structure
i. Considering the class ScriptLibrary that contain a method named printTestDetails as in following code in it:
class ScriptLibrary {
def context
def testRunner
def log
def printTestDetails(def PrintThisToo) {
log.info 'Name of the test case is :'+testRunner.testCase.name
log.info 'Name of the test suite is : '+testRunner.testCase.testSuite.name
log.info PrintThisToo
}
}
ii. Save the file with class name, ScriptLibrary.groovy in this case
Step 2: Compile the code
i. Open command prompt and fire following command (from the folder where where your .groovy file is kept)
Compile the code:
groovyc -d classes ScriptLibrary.groovy
Step 3: Create the jar file
i. After compiling the code we can create the jar
Create jar file:
jar cvf ScriptLibrary.jar -C classes .
Step 4: Deploy the jar file at SoapUI_Home/bin/ext folder
Step 5: Restart the SoapUI if was already open
Step 6: Create the object of class and use the methods anywhere in the SoapUI projects
i. Creating object
def scripts = new ScriptLibrary(context:context, log:log, testRunner:testRunner)
ii. Calling methods
scripts.printTestDetails(“This is my argument”)
I hope this solves your problem over all, this approach will allow you to freely use the code any where in the SoapUI and most importantly will solve your problem for getting context, log and testrunner in external code
You can also use any IDE of your choice to create code library and work on same to compile and create jar as well.
Let me know if you have any doubts or need more clarification
While I like Samarth's Answer for large projects, there is something about not having to leave SoapUI that makes TestHat's Answer very interesting.
This is what I used in my latest project:
A Testsuite ScriptLibrary with Testcases according to areas and Groovy script steps for every function.
I run these functions with testRunner.testCase.testSuite.project.testSuites["ScriptLibrary"].testCases["Demo"].testSteps["SomeFunction"].run(testRunner, context);, which then mutates the context to include the needed functions.
In order to use the correct log and testRunner instances, I pass those via parameters. e.g. context.someFunction(log, testRunner);
Because normal functions can't be assigned to the context, I either use closures or classes.
For classes I use something like
class SomeClass {
def logger;
def runner;
SomeClass(logger, runner) {
this.runner = runner;
this.logger = logger;
}
public static SomeClass with(logger, runner) {
return new SomeClass(logger, runner);
}
public void someFunction(String a) {
// This prints to the log of the caller function and not this one
logger.info a;
}
}
context.SomeClass = SomeClass;
and then call it with
testRunner.testCase.testSuite.project.testSuites["ScriptLibrary"].testCases["Demo"].testSteps["SomeClass"].run(testRunner, context);
context.SomeClass.with(log, testRunner).someFunction(
"Hello World"
);
This is mainly done because you can't easily create a new instance from the context.SomeClass variable.
While the context is persisted inside a Testcase, it gets cleared when using a "Run Testcase" teststep, which freqently use.
Maybe this was some help to somebody in the future.
This should do it
context.setProperty("Assertions", new Assertions());
class Assertions{
def printAssertion( tStep){
def assertions = tStep.getAssertionList()
//Loop on assertions
assertions.each{
log.info(it.name + ' --> ' + it.status)
}
}
}
and call it like this
TestStep=testRunner.testCase.testSuite.getTestCaseByName("yourTestCase").getTestStepByName("stepName")
context.Assertions.printAssertion(TestStep)
On the project level, you can write "Load Script" and you can save your utility class instance in the project level context:
context.setProperty("ScriptLibrary", new ScriptLibrary())
and in your test suit (eg. in "Setup Script") you can get it:
testSuite.project.context.getProperty('ScriptLibrary')
or in your test case:
testCase.testSuite.project.context.getProperty('ScriptLibrary')
or in your Groovy test step:
testRunner.testCase.testSuite.project.context.getProperty('ScriptLibrary')
For Assertion :
Put this script in Repository
context.setProperty("Assertions", new Assertions());
class Assertions{
def printAssertion(tStep){
def assertions = tStep.getAssertionList()
//Loop on assertions
}
}
Use this Script in SoapUI:
TestStep=testRunner.testCase.testSuite.getTestCaseByName("addTestCase").getTestStepByName("add")
//context.Assertions.printAssertion(TestStep)
scripts = testRunner.testCase.testSuite.project.testSuites["ScriptLibrary"];
scripts.testCases["Demo"].testSteps["TestAssertion"].run(testRunner, context);
context.Assertions.printAssertion(TestStep).each{
log.info(it.name + ' --> ' + it.status)
}
return null

SoapUI: Pass property values to called test case

I am a beginner in soapui testing. Hopefully you can help me solving this problem.
In my test project I have a test suites which contains several test cases. Multiple test case will start the same test case. To run this test case I need some property values to be transferred to this test case.
I tried to achieve this in two ways. But I failed in both.
I tried to call the test case and set the needed properties in the test case. I start the test case from a Groovy script. But I couldn't find a good example how to set the properties in the called test case.
I tried to get the property values of the calling parent test case inside the called test case. It looks like the parent test case that called the test case isn't available in the context of the running test case.
The test cases, that will call the same test case, will be run in parallel. So, I think it isn't a solution to first set the property values and then start the test case, because they will be overwritten by the other test cases that run at the same time. Also using test suite properties for these values won’t work because of running the test cases in parallel.
My test project looks like this.
MyProject
TestSuite_APLtests
TestCase_user_01
Properties test step
Run_test <groovy script>
Step_01
…..
TestCase_user_02
Properties test step
Run_test <groovy script>
Step_01
…..
TestCase_General
Properties test step
POST sessions
Step_01
…..
The ‘Properties test step’ of each ‘TestCase_user_’ contains a user and password needed in test case ‘TestCase_General’ and will be different for each test case.
In the ‘Run_test’ groovy script of each ‘TestCase_user_’ the test case ‘TestCase_General’ is started by using:
def myTestSuite = testRunner.testCase.testSuite.project.getTestSuiteByName("TestSuite_APLtests")
def myTestCase = myTestSuite.getTestCaseByName("TestCase_General")
myTestCase.run(null, false)
How can I add the properties user and password to the run comment that starts the test case?
If I try to get the property values with a groovy script in test case ‘TestCase_General’ I don’t know how to determine which test case has called ‘TestCase_General’. I found some posts on internet that suggests to use: context.getProperty("#CallingRunTestCaseStep#") to determine the calling test case. But this value is null. And when I try to check if the calling test case is available in the context by using: context.hasProperty("#CallingRunTestCaseStep#") this is false, so this doesn't work to find the calling test case.
Can someone tell me what the solution will be to get this working.
Thanks,
You can set Test Case properties from groovy script with setPropertyValue(name,value) method, however if you run the Test Cases in parallel, this properties as you said will be overwritten for each Test Case calling TestCase_General. So instead of use setPropertyValue you can pass the context properties through the run(StringToObjectMap properties, boolean async) method in the WsdlTestCase.java class. Your groovy code to call TestCase_General could be:
import com.eviware.soapui.support.types.StringToObjectMap
// get test suite
def myTestSuite = testRunner.testCase.testSuite.project.getTestSuiteByName("TestSuite_APLtests")
// get your test case
def myTestCase = myTestSuite.getTestCaseByName("TestCase_General")
// set the user and password properties in the context
context.setProperty("user","userTestCaseN")
context.setProperty("password","passwordTestCaseN")
// run the testCase passing the context
def contextMap = new StringToObjectMap( context )
myTestCase.run(contextMap,false);
To access the context properties in the groovy script of your TestCase_General use this code:
context.getProperty("userPassword")
Or if you prefer to use context.expand:
context.expand('${#user}')
Note that the use of # depends on how you are accessing the properties.
If you also need to use the context properties in the SOAP Test Request of your TestCase_General use this way ${#propetryName} i.e:
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Header/>
<Body>
<request>
<user>${#user}</user>
</request>
</Body>
</Envelope>
Hope this helps,

SoapUI defining a library of reusable methods

I'm running into copy-pasting a lot of code at the moment in my SoapUI projects, and thought I'd have some sort of library of helper functions that can carry out most of my tasks.
So I have a test suite for this, and the code itself is in a Groovy Script test step in this test suite. The idea is that I make my helper methods available to the context I'm in (a REST test request step).
It instantiates fine and all that, but the problem is that when I want to invoke run(testRunner, context), I am not having access to the testRunner property. I've read something about that this is how it is.
Anyone know a way around this?
I am using the same method as you for script library. I used the method described by Kerry Doan at http://www.doan.me/script-library-in-soapui-free.aspx
When i tried to access this script library from project load script i did not have access to the testRunner so i created the testRunner object and as i did not have access to the context object i had to create that too.
Check out the code below.
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner
import com.eviware.soapui.support.types.StringToObjectMap
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext
//to create the testRunner object I need a testCase object and a new StringToObjectMap
//I initially used the test case in the script library but as i needed the
//testRunner object to the test case being executed so i created the object to
//the test case being executed.
//I did not want to worry about test suite or test case names so i used their index
//assuming that there will be at least one test suite and at least one test case when
//this script is run
testCase = project.getTestSuiteAt(0).getTestCaseAt(0)
tcRunner = new WsdlTestCaseRunner( testCase, new StringToObjectMap() );
//A context is essentially a WsdlTestRunContext object and as you can see below all i
//have done to create that is pass it a test step object which was obtained by using index
//rather than name.
tStep = testCase.getTestStepAt(0)
tcContext = new WsdlTestRunContext(tStep)
//my script library is in a seperate project called `Script Library` and all the
//groovy scripts are in a test suite called `Script Library`
scripts = project.workspace.projects["Script Library"].testSuites["Script Library"];
scripts.testCases["Scripts"].testSteps["runTest"].run(tcRunner, tcContext);

Resources