I've recently started using XML Slurper and am trying to access a specific child node from a SOAP envelope. Below is an extract of the XML I'm working with:
<cons:ConsumerName>
<cons:FirstName>Robert</cons:FirstName>
<cons:MiddleName>John</cons:MiddleName>
<cons:FamilyName>Smith</cons:FamilyName>
</cons:ConsumerName>
<cons:ContactPersonName>
<cons:FirstName>William</cons:FirstName>
<cons:MiddleName>Michael</cons:MiddleName>
<cons:FamilyName>Doe</cons:FamilyName>
</cons:ContactPersonName>
I'm trying to access the value of FirstName in the ConusmerName block, I've only been able to get a list of both of the first name values by using:
def block = new XmlSlurper().parseText(text).'**'.findAll{it.name()=='FirstName'}
I tried to get the first name for the ConsumerName block only, by using:
def block = new XmlSlurper().parseText(text).'ConsumerName'.findAll{it.name()=='FirstName'}
But nothing gets returned by that, I can't work out what I'm doing wrong?
I fixed up your xml and providing an answer here:
def text = '<?xml version="1.0" encoding="UTF-8"?>' +
'<cons:Consumer xmlns:cons="urn:corp:cons">' +
' <cons:ConsumerName>' +
' <cons:FirstName>Robert</cons:FirstName>' +
' <cons:MiddleName>John</cons:MiddleName>' +
' <cons:FamilyName>Smith</cons:FamilyName>' +
' </cons:ConsumerName>' +
'' +
' <cons:ContactPersonName>' +
' <cons:FirstName>William</cons:FirstName>' +
' <cons:MiddleName>Michael</cons:MiddleName>' +
' <cons:FamilyName>Doe</cons:FamilyName>' +
' </cons:ContactPersonName>' +
'</cons:Consumer>'
def consumer = new XmlSlurper().parseText(text)
println "Consumer first name: ${consumer.ConsumerName.FirstName}"
Output:
Consumer first name: Robert
To get the firstName value in the ConsumerName block of XML, I used the following:
def text = new File(requestFilePath).text
def fieldValue = new XmlSlurper().parseText(text).'**'.findAll{it.name()==tagBlockName}.getAt(tagName)[0]
def var = (String)fieldValue
Related
I am trying to send an email through amazon SES without the SDK so I can send emails asynchronously in Python. I am using amazon's v4 signing method on their site here: https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html, but I'm not having any luck sending emails without the SDK. The output is:
RESPONSE++++++++++++++++++++++++++++++++++++
Response code: 403
<ErrorResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
<Error>
<Type>Sender</Type>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.</Message>
</Error>
<RequestId>a19a5fa1-3228-11e9-b2bc-ddb6d8a1cb1c</RequestId>
</ErrorResponse>
Process finished with exit code 0
Here is the block of code generating that response:
import datetime
import hashlib
import hmac
import urllib.parse
import requests
method = 'GET'
service = 'ses'
host = 'email.us-east-1.amazonaws.com'
region = 'us-east-1'
endpoint = 'https://email.us-east-1.amazonaws.com/'
def sign(key, msg):
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
def getSignatureKey(key, dateStamp, regionName, serviceName):
kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
kRegion = sign(kDate, regionName)
kService = sign(kRegion, serviceName)
kSigning = sign(kService, 'aws4_request')
return kSigning
access_key = '<my access_key here>'
secret_key = '<my secret_key here>'
my_email = 'my email here'
t = datetime.datetime.utcnow()
amz_date = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d')
canonical_uri = '/'
canonical_headers = 'host:' + host + '\n'
signed_headers = 'host'
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request'
canonical_querystring = '''Action=SendEmail
&Source=%s%40gmail.com
&Destination.ToAddresses.member.1=%s%40gmail.com
&Message.Subject.Data=This%20is%20the%20subject%20line.
&Message.Body.Text.Data=Hello.%20I%20hope%20you%20are%20having%20a%20good%20day''' % (my_email, my_email)
canonical_querystring += '&X-Amz-Algorithm=AWS4-HMAC-SHA256'
canonical_querystring += '&X-Amz-Credential=' + urllib.parse.quote_plus(access_key + '/' + credential_scope)
canonical_querystring += '&X-Amz-Date=' + amz_date
canonical_querystring += '&X-Amz-Expires=30'
canonical_querystring += '&X-Amz-SignedHeaders=' + signed_headers
payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest()
canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
signing_key = getSignatureKey(secret_key, datestamp, region, service)
signature = hmac.new(signing_key, (string_to_sign).encode("utf-8"), hashlib.sha256).hexdigest()
canonical_querystring += '&X-Amz-Signature=' + signature
request_url = endpoint + "?" + canonical_querystring
print('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++')
print('Request URL = ' + request_url)
r = requests.get(request_url)
print('\nRESPONSE++++++++++++++++++++++++++++++++++++')
print('Response code: %d\n' % r.status_code)
print(r.text)
This is basically Amazon's code for generating a signature copied and pasted from their docs. Does anyone know what I'm doing wrong in signing my requests to amazon?
Edit* I changed the canonical_querystring to be alphabetical like so:
canonical_querystring = '''Action=SendEmail
&Destination.ToAddresses.member.1={}%40gmail.com
&Message.Body.Text.Data=Hello.%20I%20hope%20you%20are%20having%20a%20good%20day
&Message.Subject.Data=This%20is%20the%20subject%20line.
&Source={}%40gmail.com'''.format(my_email, my_email)
It is still giving me the same error though. Everything else in the query string is alphabetized, or "canonically ordered".
Your canonical query string is not canonical.
You have Action... Source... Destination... Message but all of the parameters need to be lexically ordered.
Step 3: Create the canonical query string.
[...]
The parameters must be sorted by name.
This ordering is the reason why the value is called canonical. It's necessary because the relative positions of query string parameters aren't necessarily guaranteed. The parameters don't need to be sorted in the actual query string accompanying the request, but they do need to be sorted here, for signing.
Since a given request can have only one possible valid signature, the parameters are sorted before signing to remove the ambiguity that might otherwise arise if a user agent or proxy rearranged the query parameters or ordered them arbitrarily when building the URL (as might be expected if, for example, the parameters are passed to the UA as an unordered hash/dictionary structure).
I have a SOAP request which has dynamic values generated by random method. How to capture these generated values to log?
My SOAP request:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:web="http://www.webserviceX.NET/">
<soap:Header/>
<soap:Body>
<web:ChangeLengthUnit>
<web:LengthValue>${=(int)(Math.random()*9999)}</web:LengthValue>
<web:fromLengthUnit>Inches</web:fromLengthUnit>
<web:toLengthUnit>Centimeters</web:toLengthUnit>
</web:ChangeLengthUnit>
</soap:Body>
</soap:Envelope>
Groovy script:
import com.eviware.soapui.support.GroovyUtils;
def prj = testRunner.testCase.testSuite.project.workspace.getProjectByName("Project1")
tCase = prj.testSuites['TestSuite'].testCases['TestCase']
tStep = tCase.getTestStepByName("ChangeLengthUnit")
def stepReq = tStep.getProperty("Request").getValue()
def runner = tStep.run(testRunner, context)
log.info ("runner status ....... : " + runner.hasResponse())
log.info stepReq
for( assertion in tStep.assertionList )
{
log.info "Assertion [" + assertion.label + "] has status [" + assertion.status + "]"
for( e in assertion.errors )
log.info "-> Error [" + e.message + "]"
}
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder( stepReq.toString() )
log.info holder.getNodeValues( "//web:LengthValue" ).toString()
Above groovy script is giving output as below:
Wed Oct 18 14:55:13 SGT 2017:INFO:[${=(int)(Math.random()*9999)}]
Actual value of LengthValue tag = 3490, How to get this value ?
It can easily read from RawRequest property using Script Assertion for the same request step.
assert context.rawRequest, 'Request is empty or null'
def xml = new XmlSlurper().parseText(context.rawRequest)
def actualValueInTheRequest = xml.'**'.find{it.name() == 'LengthValue'}?.text()
log.info "Value for LengthValue in the actual request is : $actualValueInTheRequest"
I think what you're doing is getting the LengthValue from the request 'template' not what SoapUI has actually passed to the web service.
In your example, you have...
def stepReq = tStep.getProperty("Request").getValue()
The request is what you see in SoapUI that includes your vars, e.g. ${myVar}. I think what you're after is the 'raw request'.
In SoapUI, run the request and after it has ran, you should see a tab labelled 'Raw Request'. This is what SoapUI actually sends to the web service, in here you'll see that the vars have been evaluated and will show the value, which is what you are after.
I've taken your example and made some mods it. I haven't tested it, but it should help you.
import com.eviware.soapui.support.GroovyUtils;
def prj = testRunner.testCase.testSuite.project.workspace.getProjectByName("Project1")
tCase = prj.testSuites['TestSuite'].testCases['TestCase']
tStep = tCase.getTestStepByName("ChangeLengthUnit")
def stepReq = tStep.getProperty("Request").getValue()
def runner = tStep.run(testRunner, context)
// CHA MOD - Can only get raw request after running the step.
def rawRequest = context.expand( '${ChangeLengthUnit#RawRequest}' )
//CHA MOD - Quick look at the rawRequest...
log.info(rawRequest);
log.info ("runner status ....... : " + runner.hasResponse())
log.info stepReq
for( assertion in tStep.assertionList )
{
log.info "Assertion [" + assertion.label + "] has status [" + assertion.status + "]"
for( e in assertion.errors )
log.info "-> Error [" + e.message + "]"
}
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder( stepReq.toString() )
log.info holder.getNodeValues( "//web:LengthValue" ).toString()
//CHA MOD - Get the length from the raw request...
holder = groovyUtils.getXmlHolder( rawRequest.toString() )
log.info holder.getNodeValues( "//web:LengthValue" ).toString()
You are getting value from the actual request. Try to get the data from RawRequest
use below code
def holder = groovyUtils.getXmlHolder(mentionThenameofthestep#RawRequest)
The above code will point to Raw request of your teststep which contains actual value passed during execution instead of "${=(int)(Math.random()*9999)}"
So my code (pasted) below almost does what I want. Instead, it covers 29/30 pages, and then leaves out the last. Furthermore, I would preferably have it go beyond, but the website has no button for it (the pages actually do work when you manually fill in page=31 in the link). When Depth_Limit is 29 it's all fine, but on 30 I get the following error in the command prompt:
File "C:\Users\Ewald\Scrapy\OB\OB\spiders\spider_OB.py", line 23, in parse
next_link = 'https://zoek.officielebekendmakingen.nl/' + s.xpath('//a[#class="volgende"]/#href').extract()[0]
IndexError: list index out of range
I've tried various approaches, but they all seem to fail me...
class OB_Crawler(CrawlSpider):
name = 'OB5'
allowed_domains = ["https://www.officielebekendmakingen.nl/"]
start_urls = ["https://zoek.officielebekendmakingen.nl/zoeken/resultaat/?zkt=Uitgebreid&pst=Tractatenblad|Staatsblad|Staatscourant|BladGemeenschappelijkeRegeling|ParlementaireDocumenten&vrt=Cybersecurity&zkd=InDeGeheleText&dpr=Alle&sdt=DatumPublicatie&ap=&pnr=18&rpp=10&_page=1&sorttype=1&sortorder=4"]
custom_settings = {
'BOT_NAME': 'OB-crawler',
'DEPTH_LIMIT': 30,
'DOWNLOAD_DELAY': 0.1
}
def parse(self, response):
s = Selector(response)
next_link = 'https://zoek.officielebekendmakingen.nl/' + s.xpath('//a[#class="volgende"]/#href').extract()[0]
if len(next_link):
yield self.make_requests_from_url(next_link)
posts = response.selector.xpath('//div[#class = "lijst"]/ul/li')
for post in posts:
i = TextPostItem()
i['title'] = ' '.join(post.xpath('a/#href').extract()).replace(';', '').replace(' ', '').replace('\r\n', '')
i['link'] = ' '.join(post.xpath('a/text()').extract()).replace(';', '').replace(' ', '').replace('\r\n', '')
i['info'] = ' '.join(post.xpath('a/em/text()').extract()).replace(';', '').replace(' ', '').replace('\r\n', '').replace(',', '-')
yield i
The index out of range error is the result of an incorrect xpath (you end up calling for the first item of an empty list).
change your "next_link = ... " to
next_link = 'https://zoek.officielebekendmakingen.nl/' + s.xpath('//a[contains(#class, "volgende")]/#href').extract()[0]
You need to use contains, which runs a predicate search.. filters for what you want
I am currently using Jenkins version 1.617 with the latest Editable Email notification plugin.
What we are trying to do is take the changes from the build and put them into a meeting notice (Calendar Entry).
We are currently stuck using lotus notes 8.5.3FP6.
Here are our variables in the plugin:
Project Recipient List = $SERVER_GROUP
Content Type = HTML(text/html)
Default Subject = $DEFAULT_SUBJECT
Default Content =
$DEFAULT_CONTENT
Repo: myRepo
Install Location: S:\Build\VAT - Visual Authoring Tool\SERVICELOGIQ \GM\VAT_${ENV, var="miniVersion"}\VAT_${ENV, var="releaseversion"}_SERVICELOGIQ [${ENV, var="BUILD_NUMBER"}]
Change Log:
${CHANGES_SINCE_LAST_SUCCESS, reverse=true, showPaths=true}
We are trying to use the following presend script:
import javax.mail.Message
import javax.mail.Message.RecipientType
import javax.mail.Address
import javax.mail.Multipart
import javax.mail.BodyPart
import javax.mail.internet.InternetAddress
import javax.mail.internet.MimeMessage
import javax.mail.Session
import javax.mail.internet.InternetAddress
import javax.mail.internet.MimeBodyPart
import javax.mail.internet.MimeMessage
import javax.mail.internet.MimeMultipart
import javax.mail.util.ByteArrayDataSource
import java.util.Date
import java.util.Calendar
import java.util.TimeZone
import java.text.DateFormat
import java.text.SimpleDateFormat
import javax.activation.DataHandler
msg.addHeaderLine("method=REQUEST");
msg.addHeaderLine("charset=UTF-8");
msg.addHeaderLine("component=VEVENT");
final Calendar cal = Calendar.getInstance();
cal.add(Calendar.HOUR, 1);
final Date start = cal.getTime();
cal.add(Calendar.HOUR, 1);
final Date end = cal.getTime();
SimpleDateFormat dateFmt = new SimpleDateFormat("yyyyMMdd'T'hhmmssZ");
String fmtStartDate = dateFmt.format(start);
String fmtEndDate = dateFmt.format(end);
String subject = msg.getSubject()
Multipart multi = (Multipart)msg.getContent()
BodyPart part = multi.getBodyPart(0)
String body = part.getContent().toString()
String from = "jenkins#ignore.com"
Address[] toAddresses = msg.getAllRecipients()
String to = toAddresses.each{ it.toString() }.join(",")
String content =
"BEGIN:VCALENDAR\n"+
"PRODID:-//Microsoft Corporation//Outlook 9.0 MIMEDIR//EN\n"+
"VERSION:2.0\n" +
"METHOD:REQUEST\n" +
"BEGIN:VEVENT\n" +
"ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:" + to + "\n" +
"ORGANIZER:MAILTO:" + from + "\n" +
"DTSTART:" + fmtStartDate + "\n" +
"DTEND:" + fmtEndDate + "\n" +
"LOCATION:Jenkins Build\n" +
"TRANSP:OPAQUE\n" +
"SEQUENCE:0\n" +
"UID:040000008200E00074C5B7101A82E00800000000002FF466CE3AC5010000000000000000100\n" +
" 000004377FE5C37984842BF9440448399EB02\n" +
"DTSTAMP:20051206T120102Z\n" +
"CATEGORIES:Meeting\n" +
"DESCRIPTION:" + body + "\n\n" +
"SUMMARY:" + subject + "\n" +
"PRIORITY:5\n" +
"CLASS:PUBLIC\n" +
"BEGIN:VALARM\n" +
"TRIGGER:PT1440M\n" +
"ACTION:DISPLAY\n" +
"DESCRIPTION:Reminder\n" +
"END:VALARM\n" +
"END:VEVENT\n" +
"END:VCALENDAR";
// Create the message part
MimeBodyPart messageBodyPart = new MimeBodyPart();
// Fill the message
messageBodyPart.setHeader("Content-Class", "urn:content-classes:calendarmessage");
messageBodyPart.setHeader("Content-ID","calendar_message");
messageBodyPart.setDataHandler(new DataHandler(
new ByteArrayDataSource(content, "text/calendar")));//very important
// Create a Multipart
MimeMultipart multipart = new MimeMultipart();
// Add part one
multipart.addBodyPart(messageBodyPart);
// Put parts in message
msg.setContent(multipart);
This is what we understand from this script, it looks like the script is taking a email that has already been created, parsing the values and changing it into a calendar entry. However, when we run this script, it does create the calendar entry, but only gets the first line of text in the default content section of the email.
Here is an example of the email that is created:
BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 9.0 MIMEDIR//EN
VERSION:2.0
METHOD:REQUEST
BEGIN:VEVENT
ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:myemail
ORGANIZER:MAILTO:jenkins#ignore.com
DTSTART:20150716T123802-0400
DTEND:20150716T013802-0400
LOCATION:Jenkins Build
TRANSP:OPAQUE
SEQUENCE:0
UID:040000008200E00074C5B7101A82E00800000000002FF466CE3AC5010000000000000000100
000004377FE5C37984842BF9440448399EB02
DTSTAMP:20051206T120102Z
CATEGORIES:Meeting
DESCRIPTION:Check console output at http://localhost:8080/job/Test_Project_Sean2/77/ to view the results.
Repo: http://server/hg/hgweb.cgi/ServiceLogiq
Install Location: S:\Build\VAT - Visual Authoring Tool\SERVICELOGIQ\VAT_SERVICELOGIQ [77]
Change Log:
Changes for Build #77
No changes
SUMMARY:Test_Project_Sean2 Build Successful!
PRIORITY:5
CLASS:PUBLIC
BEGIN:VALARM
TRIGGER:PT1440M
ACTION:DISPLAY
DESCRIPTION:Reminder
END:VALARM
END:VEVENT
END:VCALENDAR
Our actual meeting notice is displayed like the following:
Check console output at
http://servername to
view the results.
With the email file listed above attached.
Please note that the line that was output is the DEFAULT_CONTENT variable listed above.
We have already tried the following:
def env = System.getenv()
def version = env['CHANGES_SINCE_LAST_SUCCESS']
However, this returned a NULL value.
I would appreciate any help we could get to solve our problem.
For multiple lines in a description in a calendar file, you need to put in an escaped \n instead of real newlines.
I had a scenario where I need to add my test results from a SoapUI test case to a related test case in HP Quality Center. How could I go about doing this with Groovy.
Quality Center offers an OTA API to interface with it; however, it is written to use the Microsoft COM structure which Java/Groovy has no native way to consume. Lucky, there is a Groovy library, Scriptom, that allows Groovy to consume COM interfaces.
After getting every setup, this is the sample code that I came up with:
import org.codehaus.groovy.scriptom.*
def tstCaseName = "NAME_OF_TESTCASE"
tstCaseName = tstCaseName.replaceAll(/[ ]/) { match ->
"*"
}
Scriptom.inApartment
{
// Create an entry point for QC
def tdc = new ActiveXObject ('TDApiOle80.TDConnection')
// Connect to QC, Login with Credentials, connect to Project
tdc.InitConnectionEx('http://qc.example.com/qcbin')
tdc.Login('USER_NAME', 'PASSWORD')
tdc.Connect('DOMAIN_NAME','PROJECT_NAME')
// Find the set of tests in the Test Plan
tsFolder = tdc.TestSetTreeManager.NodeByPath('Root\\PATH\\TO\\TEST\\CALENDAR\\Spaces are allowed')
tsList = tsFolder.FindTestSets('NAME_OF_TEST_CALENDAR')
tsObject = tsList.Item(1)
// Get the list of TestCases in the Test Plan and filter it down to the one Test Case we are interested in
TSTestFact = tsObject.TSTestFactory
tstSetFilter = TSTestFact.Filter
tstSetFilter.Filter["TS_NAME"] = '*' + tstCaseName
TestSetTestsList = TSTestFact.NewList(tstSetFilter.Text)
tsInstance = TestSetTestsList.Item(1)
// Create a new Test Run
newRun= tsInstance.RunFactory.AddItem('Run_Auto')
newRun.Status = 'Not Completed'
newRun.Post()
newRun.CopyDesignSteps()
newRun.Post()
// Populate Auto Run Test step Data
def tsStepData = new Object[3]
tsStepData[0]='Auto Data'
tsStepData[1]='Not Completed'
tsStepData[2]='Results from Automated Test'
// Create new Test Step in the run with our Auto Run Data
tsSteps = newRun.StepFactory.AddItem(tsStepData)
tsSteps.Field['ST_ACTUAL'] = 'These are the actual results from my test!!'
tsSteps.post()
}
I had issues with the scriptom and being new to Groovy but having experience with Quality Center I wrote a tear down script for my SoapUI test that writes my results to a flat file and then I use the VBScript to pull the data in.
These scripts use hard coded values but hopefully will get you started:
VAPI-XP Script - http://ryanoglesby.net/2013/08/23/executing-soapui-from-quality-center-part-1/
'*******************************************************************
'Debug, CurrentTestSet, CurrentTest, CurrentRun
'Debug, CurrentTestSet, CurrentTSTest, CurrentRun
'**************************************************************************
Sub Test_Main(Debug, CurrentTestSet, CurrentTest, CurrentRun )
' *** VBScript Limitation ! ***
' "On Error Resume Next" statement suppresses run-time script errors.
' To handle run-time error in a right way, you need to put "If Err.Number <> 0 Then"
' after each line of code that can cause such a run-time error.
On Error Resume Next
'Clear output window
TDOutput.Clear
'**************************************************************************
' Define the path for SOAPUI executable bat file and Project xml
' Project xml contains the test case(s) that need to be executed
'**************************************************************************
Dim trPath 'Path to test runner bat file
Dim soapResults 'Result file generated by SoapUI Groovy Script
Dim projFP 'SoapUI Project File Path
Dim spath 'Result File - Currently not using
Dim tf 'Test Factory Object
Dim ts 'Test ID
Dim TSuite 'SoapUI Test Suite Name
Dim Tcase 'SoapUI Test Case Name
Dim resultsP 'SoapUI output Report Location - Currently Not using
projFP = "C:\SOME\FILE\PATH\soapui-project.xml"
spath = "C:\File.txt"
trPath = "C:\program files\SmartBear\SoapUI-Pro-4.5.2\bin\testrunner.bat"
soapResults = "C:\Groovy_Report\test1.txt"
'Strings for SoapUI Execution
TSuite="SOAPUI_TESTSUITE_NAME"
Tcase="SOAPUI_TESTCASE_NAME"
resultsP="C:\SoapResults\" & Tcase
Set tf = TDConnection.TestFactory
Set ts = tf.Item(Field("TS_TEST_ID"))
'**************************************************************************
' Invoke SOAPUI and execute the selected project
'**************************************************************************
invokeSOAPUIClient trPath, projFP, TSuite, Tcase, resultsP, CurrentTest, CurrentRun
'**************************************************************************
' Get the Results from the text file in to Run Steps of the test case
'**************************************************************************
'wait 1 second to allow for larger files to complete writing
TDOutput.Print "Start Wait 10"
XTools.Sleep 1000
TDOutput.Print "END Wait 10"
'Get Result file and write to run steps
getResultsToQC CurrentRun, soapResults
'**************************************************************************
' handle run-time errors
'**************************************************************************
If Not Debug Then
If Err.Number <> 0 Then
TDOutput.Print "Run-time error - Execute SOAPUI:Enter SuB - [" & Err.Number & "] : " & Err.Description
CurrentRun.Status = "Failed"
CurrentTest.Status = "Failed"
Else
CurrentRun.Status = "Passed" 'Need Function here to determine if all steps passed
CurrentTest.Status = "Passed" 'Need Function here to determine if all steps passed
End If
End If
End Sub
'**************************************************************************
' Sub for executing SOAPUI with the selected project
'**************************************************************************
' soapuiTestrunnerPath: TestRunner .bat file
' projectLocation: Project file location
'**************************************************************************
Sub invokeSOAPUIClient(soapuiTestrunnerPath, projectLocation, TSuite, Tcase, resultsP, CurrentTest, CurrentRun)
'**************************************************************************
' Execute SOAPUI from the command line
' Output Test Values for reference - Not Required
'**************************************************************************
TDOutput.Print "TSuite: " & TSuite
TDOutput.Print "Tcase: " & Tcase
TDOutput.Print "resultsP: " & resultsP
set fileSystem = CreateObject("Scripting.FileSystemObject")
'**************************************************************************
' Raise error if SOAPUI is not installed in the host where program is
' runned or if the path of executable bat file provided is not correct
'**************************************************************************
If ( not fileSystem.FileExists(soapuiTestrunnerPath)) then
Err.Raise 8
Err.Description = "soapUI testrunner not found: " + soapuiTestrunnerPath
End if
'**************************************************************************
'args will be the options that you wish to pass to the TestRunner
'for a full list of options call the test runner from the command prompt with
'no options
'**************************************************************************
Dim args
'args = "-s" & chr(34) & TSuite & chr(34) & " -c" & chr(34) & TCase & chr(34) & " -Drpath=" & resultsP & " -r -a -I "& chr(34) & projectLocation & chr(34) &""
args = "-s" & TSuite & " -c" & TCase & " -M -j -F XML -R test.xml -f " & resultsP & " -r -g -A -I "& chr(34) & projectLocation & chr(34) &""
XTools.run soapuiTestrunnerPath, args, -1, true
End Sub
'**************************************************************************
' Sub for Adding Results to QC - Parent to addRunData() function
' function will parse the result file generated by SoapUI Groovy Script &
' add the run details for the Soap UI test to the QC run
'**************************************************************************
' sFile: File path to Groovy Script Results "C:\Groovy_Report\test1.txt"
' Currently this value is HARD CODED
'**************************************************************************
sub getResultsToQC(CurrentRun, sFile)
Set objFS = CreateObject("Scripting.FileSystemObject")
'Create object for result file
Set objFile = objFS.GetFile(sFile)
'OPen Stream to read in file
Set ts = objFile.OpenAsTextStream(1,-2)
'Loop through file line by line
Do Until ts.AtEndOfStream
'Create string value for current line
strLine = ts.ReadLine
'TDOutput.Print strLine
'Split values based on delimiter (Set in groovy Script)
ArrSplit=Split(strLine, "|")
size = Ubound(ArrSplit)
'Determine action for array values
'Size = 6 is a report value that will have pass/fail
'Size <> 6 is a info value and will have status = N/A
if(size=6) Then
'StepName
sStepName = ArrSplit(1) & "-" & ArrSplit(2)
'Clean Step Status and determine pass/fail
sSplit = Split(ArrSplit(4),":")
sValue = Trim(sSplit(1))
if(sValue="VALID")Then
sStatus = "Passed"
Elseif (sValue="FAILED") then
sStatus = "Failed"
Else
sStatus = "N\A"
End If
'Step Description
sDescription = ArrSplit(5)
'Step Expected
sExpected = ArrSplit(3)
'Step Actual
sActual = Trim(ArrSplit(6))
'Add run result to current execution run
addRunData CurrentRun, sStepName, sStatus, sDescription, sExpected, sActual
else
'Added in case other options arise in the future
if(Trim(ArrSplit(0)) = "INFO") Then
sStepName = "INFO - " & ArrSplit(1)
sStatus = "N/A"
sDescription = ArrSplit(1)
sExpected = "N/A"
sActual = ArrSplit(2)
addRunData CurrentRun, sStepName, sStatus, sDescription, sExpected, sActual
End If
End if
Loop
ts.Close
end sub
'**************************************************************************
' Sub for adding Test Steps to the current run
' function will add the run details for the Soap UI test to the QC run
'**************************************************************************
' sStepName: Passed from getResultsToQC - String to display the step name
' sStatus: Passed from getResultsToQC - String to determine step status
' sDescription: Passed from getResultsToQC - String to describe step
' sExpected: Passed from getResultsToQC - String to show expected value
' sActual: Passed from getResultsToQC - String to show actual value
'**************************************************************************
Sub addRunData(CurrentRun, sStepName, sStatus, sDescription, sExpected, sActual )
Dim objRun
Set objRun = CurrentRun
'Create Step object and add values to Object array
Set objStep = objRun.StepFactory.AddItem(null)
objStep.Field("ST_STEP_NAME")= sStepName
objStep.Field("ST_STATUS") = sStatus
objStep.Field("ST_DESCRIPTION") = sDescription
objStep.Field("ST_EXPECTED") = sExpected
objStep.Field("ST_ACTUAL") = sActual
objStep.Post
Set objStep = Nothing
end sub
Groovy SoapUI TearDown Script - http://ryanoglesby.net/2013/08/28/executing-soapui-from-quality-center-part-2-groovy-teardown-script/
import jxl.*
import jxl.write.*
import java.lang.*
import com.eviware.soapui.support.XmlHolder
//*********************************************************************
//Define Array to hold reporting data
//*********************************************************************
def reportInfo = []
//*********************************************************************
//Define test name
//*********************************************************************
def testName= testRunner.testCase.name.toString()
def fpath = context.expand( '${projectDir}' )
def tcase = testRunner.testCase
//*********************************************************************
//Get number of Test steps
//*********************************************************************
def size = testRunner.testCase.getTestStepCount();
//*********************************************************************
//loop through test steps
//*********************************************************************
for(int i = 0; i<size; i++){
//*********************************************************************
//get Step Name
//*********************************************************************
name = tcase.getTestStepAt(i).getName()
//*********************************************************************
//create test step object
//*********************************************************************
testStep = testRunner.getTestCase().getTestStepByName(“$name”)
//*********************************************************************
//Get test step type
//*********************************************************************
def stepType = testStep.config.type
//*********************************************************************
//Determine course of action for each step type
//*********************************************************************
if(stepType==”datasink”){
//*********************************************************************
//Info Step as we won’t be running assertions on this step type
//Data will be added to reportInfo Array
//*********************************************************************
def info = “INFO | Data Sink Step | “+name
reportInfo << info
}else if(stepType==”groovy”){
//*********************************************************************
//Info Step as we won’t be running assertions on this step type
//Data will be added to reportInfo Array
//*********************************************************************
def info = “INFO | Groovy Script Step | “+name
reportInfo << info
}else if(stepType==”request”){
//*********************************************************************
//Report Step as we WILL be running assertions on this step type
//Data will be added to reportInfo Array
//*********************************************************************
//Create List of Assertion names, Counter == alist Size, and
//Assertion status
//*********************************************************************
def assertionNameList = testStep.getAssertionList().name
def counter = assertionNameList.size()
def assertionStatus = testStep.getAssertionList()
//*********************************************************************
//Loop through assertionList
//*********************************************************************
for(j=0;j<counter;j++)
{
def iAssertionName = assertionNameList[j]
def iAssertionStatus = testStep.getAssertionAt(j).getStatus().toString()
def tstep = testStep.getName()
if(iAssertionName==”SOAP Response”){
//*********************************************************************
//If Assertion type is SOAP Response Capture Step Status and XML
//*********************************************************************
def response = context.expand( ‘${‘+tstep+’#Response}’ )
response = response.replace(“\n”, “”)
response = response.replace(“\r”, “”)
def type = testStep.getAssertionAt(j).config.type
def reportString = “Report | ” + tstep + ” | ” + iAssertionName + ” | Expected Success Response |” + “Status: ” + iAssertionStatus + ” | ” + type + ” | ” + response
log.info reportString
reportInfo << reportString
}else{
//*********************************************************************
//If Assertion type is NOT SOAP Response Capture:
// Step Status
// Expected Value
// Assertion Type
// Actual (If Error=Error Message Else = Expected)
//*********************************************************************
def expect = testStep.getAssertionAt(j).expectedContent
def expectedValue = context.expand(expect)
def gStatus = testStep.getAssertionAt(j).status
gStatus = gStatus.toString()
def gAssert = testStep.getAssertionAt(j)
def gType = testStep.getAssertionAt(j).config.type
if(gStatus!=’FAILED’){
def reportString = “Report | ” + tstep + ” | ” + iAssertionName + ” | Expected: ” + expectedValue + “|” + ” Status: ” + gStatus + “|” + ” Type: ” + gType + “|” + expectedValue
log.info reportString
reportInfo << reportString
}else{
for( e in testStep.getAssertionAt(j).errors ){
def reportString = “Report | ” + tstep + ” | ” + iAssertionName + ” | Expected: ” + expectedValue + “|” + ” Status: ” + gStatus + “|” + ” Type: ” + gType + “|” + ” Error [" + e.message + "]”
log.info reportString
reportInfo << reportString
}
}
}
}
}else{
//*********************************************************************
//We will want to log a message for this step
//for currently unhandled step types
//*********************************************************************
}
}
//*********************************************************************
//capture execution time
//*********************************************************************
def gTimeInfo = “INFO | TIME | “+testRunner.getTimeTaken()
reportInfo << gTimeInfo
log.info gTimeInfo
//*********************************************************************
//create report for test
//*********************************************************************
//Folder within directory to save results to. If folder does not exist
//we will create it
//*********************************************************************
def folder = “Groovy_Report”
//*********************************************************************
//Directory to place create folder in or location of Folder
//*********************************************************************
def dir = “c:/”
//*********************************************************************
//Define and execute folder creation method
//*********************************************************************
def c
c = createFolder(dir,folder)
//*********************************************************************
//Define test file name and create report file
//*********************************************************************
def fName = “test1″
createfile(c,”fName”,”.txt”,reportInfo)
//*********************************************************************
//Create File Method
//*********************************************************************
//Input:
// dir: root folder directory
// filenm: name of file to be created minus the extension
// ext: file extension to be used
// info: array of strings containing your file data
//*********************************************************************
public void createfile(def dir, def filenm, def ext, def info){
new File(“$dir/$filenm$ext”).withWriter { out ->
info.each {
out.println it
}
}
}
//*********************************************************************
//Create File Method
//*********************************************************************
//Input:
// dir: root folder directory
// folder: folder to add to directory
//Output:
// String: directory root for file creation
//*********************************************************************
public String createFolder(def dir,def folder){
File f = new File(“$dir/$folder”);
f.mkdirs();
return “$dir/$folder”
}