Below is have a piece of code that handle an alert which contains a drop down:
SoapUI Project Setup Script
import com.eviware.soapui.support.*
def alert = com.eviware.soapui.support.UISupport
def urls = []
project.properties.each
{
if (it.value.name.startsWith("BASE_URL_"))
{
urls.push(it.value.name.replace("BASE_URL_", ""))
}
}
def urlName = alert.prompt("Please select the environment URL", "Enter URL", urls)
What i have noticed is that when I select the x button to close the alert, it still runs the test (which will fail as I have not selected an environment. My question is that how can I write the code so that if the alert is closed (click the x button), it doesn't run the test?
Thank you
Usually, user don't cancel the project execution.
But there is layer that you wrote on top of it before the execution of the project which will actually selects the domain address in the prompt and then cancel as user do not wish to run the project.
Right now, the script you wrote is not doing any condition check. In order to achieve what you are looking for is to have the condition to know if user has clicked on Ok or otherwise do not execute the test suites.
Here is the modified Project level Setup Script:
import static com.eviware.soapui.support.UISupport.prompt
def urls = []
def prefix = 'BASE_URL_'
project.properties.each {
if (it.value.name.startsWith(prefix)) {
urls.push(it.value.name.replace(prefix, ""))
}
}
def suffix = prompt("Please select the environment URL", "Enter URL", urls)
if (suffix) {
log.info 'received user input'
def propertyName = prefix+suffix
def domainAddress = project.getPropertyValue(propertyName)
log.info "Selected environment : ${propertyName} - ${domainAddress}"
} else {
log.warn 'haven\'t received user input'
log.warn 'No base URL is selected or cancelled, try again'
assert false
}
Related
I wrote a groovy script for Jira Epic workflow that enables to close the Epic only if all the child issues are closed.
The script works great, and now I want to make it valid only for a specific type of linked issue. "Issues in epic"
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.link.IssueLinkManager
import com.opensymphony.workflow.InvalidInputException
// Allow logging for debug and tracking purposes
import org.apache.log4j.Level
import org.apache.log4j.Logger
// Script code for easy log identification
String scriptCode = "Check all issues in Epics are Done -"
// Setup the log and leave a message to show what we're doing
Logger logger = log
logger.setLevel( Level.ERROR )
logger.debug( "$scriptCode Triggered by $issue.key" )
def passesCondition = true
if (issue.issueType.name == 'Epic')
{
IssueLinkManager issueLinkManager = ComponentAccessor.issueLinkManager
def found = issueLinkManager.getOutwardLinks(issue.id).any
{
it?.destinationObject?.getStatus().getName() != 'Done' &&
it?.destinationObject?.getIssueType().getName() != 'Epic'
}
logger.debug( "$scriptCode Found = $found " )
if (found) {
logger.debug( "$scriptCode return false" )
passesCondition = false
invalidInputException = new InvalidInputException("Please make sure all linked issues are in 'Done' status")
} else {
logger.debug( "$scriptCode return true" )
passesCondition = true
}
}
// Always allow all other issue types to execute this transition
else
{
logger.debug( "$scriptCode Not Epic return true")
passesCondition = true
}
The code above works for all kinds of linked issues.
Does anyone know how to make it works only for a specific link type?
Thanks.
You can use
it?.issueLinkType
inside the Closure.
Then you can use
it?.issueLinkType.inward
and
it?.issueLinkType.outward
to get the inward/outward name of the link type.
I have a soap project with 4 Test Suite,each Test Suite has some Test Case and each Test case has some test steps[Soap Request,Groovy Script]
I am able to access all the properties using mentioned code below , HOWEVER,code is writing blank request/response file in local system **
def Project = testRunner.testCase.testSuite.project;
for(def i=0;i<Project.testSuiteCount;i++)
{
log.info Project.getTestSuiteAt(i).name
def Suite = Project.getTestSuiteAt(i)
for(def j=0;j<Suite.testCaseCount;j++)
{
log.info Suite.getTestCaseAt(j).name
def TCase = Suite.getTestCaseAt(j)
for(def k=0;k < TCase.testStepCount;k++)
{
def TStep= TCase.getTestStepAt(k)
def req = context.expand('${'+TStep.name+'#Request}')
new File("D:/Directory/"+Suite.name+"_"+TCase.name+"_"+TStep.name+"_"+k+".txt").write( req )
}
}
}
** plz help to solve this, **
Actually there are multiple approaches to achieve this.
Below is the one of the approach.
Here is Groovy Script which writes the requests and responses.
This script assumes that user has already run the test suites so that responses are available to be saved.
Create a new test suite -> test case -> add Groovy Script test step and copy the below script into it.
Groovy Script:
/**
* This groovy script saves the request and response
* And this script will be able to write the responses
* into files if and only if there is response available
**/
import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep
//Change direcoty path if required
def directoryToSave = 'D:/directory'
//Not required to change the script beyond this point
//date time is appended to the file name
def dt = new Date().format('yyyyMMdd_HHmmss')
//Closure to save the file
def saveToFile(file, content) {
if (!file.parentFile.exists()) {
file.parentFile.mkdirs()
log.info "Directory did not exist, created"
}
if (content) {
log.info "Writing the content into file :${file.name}"
file.write(content)
assert file.exists(), "${file.name} not created"
} else {
log.warn "the content is empty, not writing the content into file"
}
}
//Get the project object
def project = context.testCase.testSuite.project
//Loop thru the project and save the request and responses
project.testSuiteList.each { suite ->
suite.testCaseList.each { kase ->
kase.testStepList.each { step ->
if (step instanceof WsdlTestRequestStep) {
def reqFilePath = new File("${directoryToSave}/${suite.name}_${kase.name}_${step.name}_request${dt}.xml")
def resFilePath = new File("${directoryToSave}/${suite.name}_${kase.name}_${step.name}_response${dt}.xml")
saveToFile(reqFilePath, step.testRequest.requestContent)
saveToFile(resFilePath, step.testRequest.responseContent)
saveToFile(step)
} else {
log.info "Ignoring as the step type is not Soap request"
}
}
}
}
I am writing groovy script to save raw soap request & response and i get this error:
groovy.lang.MissingPropertyException: No such property: file for class: Script7 error at line 5
Here is the Script:
def myOutFile = context.expand( '${#TestSuite#fileName}' )+"_PostPaid-Success_Payment_BillInqReq.xml"
def response = context.expand( '${BillInq#Request}' )
def f = new File(myOutFile)
f.write(response, "UTF-8")
file.write(context.rawRequest,'utf-8')
Please follow the steps below:
Go to Test Suite PostPaid
Add a custom property say DATA_STORE_PATH and its value to a directory name where you like to save the requests and responses
Go to test case PostPaid_Success_Payment
Disable the Step 2 & Step 3 i.e., SaveInquiryReq and SaveInquiryResponse steps. or you may remove altoger as well if no other work is done apart from save the request & response respectively.
Click on step1 BillInq, click on assertions, Choose Script Assertion, see here for more details how to add script assertion
Have below script and click ok
Now you run the step1, you should be able to see the request and responses saved in the above mentioned directory
/**
* This script logs both request and response
*/
assert context.response, "Response is empty or null"
assert context.request, "Request is empty or null"
//Save the contents to a file
def saveToFile(file, content) {
if (!file.parentFile.exists()) {
file.parentFile.mkdirs()
log.info "Directory did not exist, created"
}
file.write(content)
assert file.exists(), "${file.name} not created"
}
def dirToStore = context.expand('${#TestSuite#DATA_STORE_PATH}')
def currentStepName = context.currentStep.name
def requestFileName = "${dirToStore}/${currentStepName}_request.xml"
def responseFileName = "${dirToStore}/${currentStepName}_response.xml"
//Save request & response to directory
saveToFile(new File(requestFileName), context.rawRequest)
saveToFile(new File(responseFileName), context.response)
I have a groovy script that I've added code to to check if a value exists in an XML response I'm getting within SoapUI. I've been dealing with this for a few days and could use some help.
Here is the code:
import com.eviware.soapui.support.XmlHolder
import com.eviware.soapui.impl.wsdl.teststeps.registry.RestRequestStepFactory
// read your request template
def requestFile = new File("C:/XMLRequestScript/file.xml");
// parse it as xml
def requestXml = new XmlHolder(requestFile.text)
// get the current testCase to add testSteps later
def tc = testRunner.testCase;
// get the testStep as template to create the other requests
def tsTemplate = tc.getTestStepByName("Template");
// loop to create # of testSteps for each application
for(int i = 1; i < 3; i++) {
// xpath expression to get applicationNumber attribute in root node
def xpathNodeAttr = "/*/#ApplicationNumber";
// get the root node attribute applicationNumber throught an XPATH
int appId = Integer.parseInt(requestXml.getNodeValue(xpathNodeAttr));
// add 1 to appId
appId++;
// set the value again in the attribute
requestXml.setNodeValue(xpathNodeAttr,appId);
// create next testStepName for new Application
def testStepName = "TestStep_ApplicationNumber_" + String.valueOf(appId)
log.info testStepName;
log.info testStepName.getClass().getName()
log.info tc.getClass().getName()
// create a new testStepConfig
def testStepFactory = new RestRequestStepFactory();
def testStepConfig = testStepFactory.createConfig( tsTemplate.getTestRequest(), testStepName )
// add the new testStep to TestCase
def newTestStep = tc.insertTestStep( testStepConfig, -1 )
// set the request
newTestStep.getTestRequest().setRequestContent(requestXml.getXml())
// add Assertions here
def assertion = tc.getTestStepByName(newTestStep.toString()).addAssertion("Contains")
if (assertion.contains("Champion5")) {
newTestStep.addAssertion("Champion5")
log.info("REST response assertion created into: " + newTestStep)
} else {
log.info("REST response assertion not found in " + newTestStep)
}
if (assertion.contains("Challenger5")) {
newTestStep.addAssertion("Challenger5")
log.info("REST response assertion created into: " + newTestStep)
} else {
log.info("REST response assertion not found in " + newTestStep)
}
// execute the request
newTestStep.run(testRunner, context)
}
In the section above called "// add Assertions here", the line of code that I'm having a problem with is:
def assertion = tc.getTestStepByName(newTestStep.toString()).addAssertion("Contains")
The error states:
Thu Sep 18 14:27:57 CDT 2014:ERROR:An error occurred [Cannot invoke method addAssertion() on null object], see error log for details
My understanding is that I have to pass an Assertion Type that is contained in the SoapUI GUI and just put it in as a string value in order to check if the values that I'm checking are asserted.
Any suggestions/direction would be appreciated. I have no idea what I'm doing wrong. Thanks.
I think the problem is your are calling the function tc.getTestStepByName(String name) with a wrong name, because the newTestStep.toString() doesn't return the Test step name instead it returns the class name (it really returns 'classname' + '#' + 'Integer.toHexString(hashCode())' if it's not override it, see Object.toString()) .
Anyway what you want is to add an assertion for a test step which is just created so add the assertion directly to it instead to find it by name, use:
def assertion = newTestStep.addAssertion("Contains")
instead of:
def assertion = tc.getTestStepByName(newTestStep.toString()).addAssertion("Contains")
The second problem you have is that you're using the assertion incorrectly. The assertion object in your case is an instance of SimpleContainsAssertion and contains() method doesn't exist in this class, to set the string to check in contains assert use setToken() method, I think that you need this to add the two assertions:
def assertion = newTestStep.addAssertion("Contains")
// add token to check
assertion.setToken("Champion5")
// change assert name in order to avoid the popup
// when we create the second one.
assertion.setName("CONTAINS 1")
// create a second assertion
assertion = newTestStep.addAssertion("Contains")
assertion.setToken("Challenger5")
assertion.setName("CONTAINS 2")
instead of :
// add Assertions here
def assertion = tc.getTestStepByName(newTestStep.toString()).addAssertion("Contains")
if (assertion.contains("Champion5")) {
newTestStep.addAssertion("Champion5")
log.info("REST response assertion created into: " + newTestStep)
} else {
log.info("REST response assertion not found in " + newTestStep)
}
if (assertion.contains("Challenger5")) {
newTestStep.addAssertion("Challenger5")
log.info("REST response assertion created into: " + newTestStep)
} else {
log.info("REST response assertion not found in " + newTestStep)
}
This code will result creating this two asserts, one named "CONTAINS 1" and check that response contains the string "Champion5", and a second one named "CONTAINS 2" and check that response contains the string "Challenge5".
Hope this helps,
I have prepared a test case in SoapUI Open Source which loops over values in csv file and sends request for each set of values (taken care of by groovy script). I want to modify it so each thread for each new iteration uses value from next row of csv file.
import com.eviware.soapui.impl.wsdl.teststeps.*
def testDataSet = []
def fileName = "C:\\sSHhrTqA5OH55qy.csv"
new File(fileName).eachLine { line -> testDataSet.add( line.split(",") ) }
def myProps = new java.util.Properties();
myProps = testRunner.testCase.getTestStepByName("Properties");
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context );
def testCase = testRunner.testCase;
def testStep = testCase.getTestStepByName("TestRequest");
testRunner = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner(testCase, null);
testStepContext = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext(testStep);
while (true) {
for ( i in testDataSet ) {
myProps.setPropertyValue("parameter0",i[0]);
myProps.setPropertyValue("username",i[1]);
myProps.setPropertyValue("parameter1",i[2]);
myProps.setPropertyValue("password",i[3]);
testStep.getTestRequest().setUsername(myProps.getPropertyValue("username"))
testStep.getTestRequest().setPassword(myProps.getPropertyValue("password"))
testStep.run(testRunner, testStepContext);
}
}
I want to modify this script so each thread from the pool gets unique (next) unused value from data source
I tried to use newFixedThreadPool from java.util.concurrent as suggested here (Concurrency with Groovy), however I can't get it to work - either requests are duplicated or SoapUI crashes (I am new to concurrency).
Can you please help me to get it right?
I think this would work for you:
while (true) {
for ( i in testDataSet ) {
def th = Thread.start(){
myProps.setPropertyValue("parameter0",i[0]);
myProps.setPropertyValue("username",i[1]);
myProps.setPropertyValue("parameter1",i[2]);
myProps.setPropertyValue("password",i[3]);
testStep.getTestRequest().setUsername(myProps.getPropertyValue("username"))
testStep.getTestRequest().setPassword(myProps.getPropertyValue("password"))
testStep.run(testRunner, testStepContext);
}
th.join()
}
So, new threads would be created on each loop.
If you wanted to test out if its working you could place loginfo(s) in the code...
log.info("Thread Id: " + Thread.currentThread().getId() as String)
I don't see your point. SoapUi already gives you a datasource test step that accepts a csv file as input.
So once you have all these values you can transfer the properties and run the test.