unable to parse xml with groovy - jenkins

I can't read the xml and parse the items because it's always returning an error of
groovy.lang.MissingPropertyException: No such property: method for
class: Script1
def xmlText = new XmlSlurper().parse('myxml.xml')
def skipped = 0
def failed = 0
def total = 0
def passed = 0
xmlText.suite.test.class.test-method.each{
if(it['#is-config'] == "true"){
}
else{
if(it['#status']=="PASS"){
passed = passed + 1
total = total + 1
}
if(it['#status']=="FAIL"){
failed = failed + 1
total = total + 1
}
if(it['#status']=="SKIP"){
skipped = skipped + 1
total = total + 1
}
}
}
the xml file is
<?xml version="1.0" encoding="UTF-8"?>
<testng-results skipped="3" failed="0" total="3" passed="0">
<reporter-output>
</reporter-output>
<suite name="DinamicTestSuite" duration-ms="24" started-at="2018-07-16T13:26:48Z" finished-at="2018-07-16T13:26:48Z">
<groups>
</groups>
<test name="Device:null" duration-ms="24" started-at="2018-07-16T13:26:48Z" finished-at="2018-07-16T13:26:48Z">
<class name="com.automation.venues.stg.VenuesSuite">
<test-method status="PASS" signature="login(org.testng.ITestContext, java.lang.String)[pri:0, instance:com.automation.venues.stg.VenuesSuite#71454b9d]" name="login" is-config="true" duration-ms="11" started-at="2018-07-16T16:26:48Z" finished-at="2018-07-16T16:26:48Z">
</test-method>
<test-method status="PASS" signature="beforeMethod(java.lang.reflect.Method)[pri:0, instance:com.automation.venues.stg.VenuesSuite#71454b9d]" duration-ms="0" started-at="2018-07-16T16:26:48Z" finished-at="2018-07-16T16:26:48Z">
</test-method>
</class> <!-- com.automation.venues.stg.VenuesSuite -->
</test> <!-- Device:null -->
</suite> <!-- DinamicTestSuite -->
</testng-results>
how can I parse the list ?

You need to put quotes round the attribute with a - in it
xmlText.suite.test.class.'test-method'.each{
An alternative to your each approach would be:
def xmlText = new XmlSlurper().parse('myxml.xml')
def totals = xmlText.suite.test.class.'test-method'.countBy { it.#status.text() }
def skipped = totals.SKIP
def failed = totals.FAIL
def passed = totals.PASS
def total = totals.values().sum()

Related

XQuery: How to get a specific value out of a tag?

Suppose we have this xml:
<question>
<test id="1">
<tag k="a" v="1"/>
<tag k="a" v="2"/>
<tag k="b" v="3"/>
</test>
<test id="2">
<tag k="a" v="1"/>
<tag k="a" v="4"/>
<tag k="b" v="5"/>
</test>
<test id="3">
<tag k="a" v="2"/>
<tag k="a" v="6"/>
<tag k="b" v="7"/>
</test>
</question>
I would like to return all values v of test, if k = "a" AND v = "1", like this:
v="3"
v="5"
So far my approach:
for $i in //test
where ($i/tag[#k = 'a' and #v = '1'])
return $i/tag/#v
But this is not correct because thats the return:
v="1"
v="2"
v="3"
v="1"
v="4"
v="5"
Thank you for your help :)
You are probably looking for something like
for $i in //test
where ($i/tag[#k = 'a'][#v="1"])
return $i/tag[#k="b"]/#v
Your criteria for selection was not exactly clear, but this returns what you expected:
for $i in //test
where $i/tag[#k = 'a' and #v = '1']
return $i/tag[not(#k = 'a' or #v = '1')]/#v
You could simplify and do this in a single XPath expression:
//test/tag[#k = 'a' and #v = '1']/tag[not(#k = 'a' or #v = '1')]/#v

In groovy script in jenkins test result how can we get information on skipped tests to show if test was expectedFailure(pass or fail) or Skipped?

The jenkins test result GUI shows skipped or expectedFail tests as skipped.
The individual test view for skipped or expectedFail tests shows "Skipped Message" and "Standard Output"
e.g. "Skipped Message" can be:
a custom skip message
* e.g. from python #unittest.skip("some reason") tag or
* e.g. raise unittest.SkipTest("thing not found.")
"expected test failure"
"xfail-marked test passes unexpectedly"
We are using groovy script to generate test reports.
We would like to include more information about skipped tests rather than just "skipped".
How can we get info on the skipped test like in the "Skipped Message" in the GUI view?
The jenkins API is documented here:
https://javadoc.jenkins.io/plugin/junit/hudson/tasks/junit/TestResult.html
There is no specific call for getting information on the skipped or expectedFail tests.
I am hoping with some experimentation that it will be possible to get expectedFail information through this testResult API.
Starting with these API calls:
String getErrorDetails()
If there was an error or a failure, this is the text from the message.
String getErrorStackTrace()
If there was an error or a failure, this is the stack trace, or otherwise null.
String getName()
Gets the name of this object.
String getStderr()
The stderr of this test.
String getStdout()
The stdout of this test.
TestResult getTestResult()
Returns the top level test result data.
String getTitle()
Gets the human readable title of this result object.
In the GUI:
A normal passed test just has "Standard Output".
A normal failed test has "Error Message" and "Stacktrace" and "Standard Output".
A skipped or expectedFail tests shows "Skipped Message" and "Standard Output".
We are using python unittest outputting junit test result files.
Loading that into jenkins using junit test result plugin.
Have I missed something in the jenkins test results API that would give more information on expected fail or skipped tests ?
I hope to find the info through experimentation using the API.
And document it in an answer here.
Here is the guts of test report groovy script
(used in jenkins Execute Groovy Script plugin
after jUnit result plugin has harvested test results):
import hudson.model.*
def build = Thread.currentThread().executable
workspace = build.getEnvVars()["WORKSPACE"]
reportfilename = workspace + "/testreport.html"
rf = new File(reportfilename);
def testCount = "0"
def testPassed = "0"
def testFailed = "0"
def testSkipped = "0"
def buildDuration = "0"
def workspace = "unknown"
def buildName = "unknown"
def BUILD_STATUS = ""
def BUILD_URL = ""
def testResult = null
def testResult1 = null
def testResult2 = null
def testDuration = ""
def caseResult = null
def buildNumber = 0
def buildNumHash = ""
def buildTimeString = ""
def rooturl = ""
try {
buildNumber = build.number
buildNumHash = build.getDisplayName()
//currentBuildNumber = manager.build.number
buildTimeString = build.getTime().format("YYYY-MMM-dd HH:mm:ss")
if(build.testResultAction) {
testResult = build.testResultAction
testCount = String.format("%d",(testResult.totalCount))
testPassed = String.format("%d",(testResult.result.passCount))
testFailed = String.format("%d",(testResult.result.failCount))
testSkipped = String.format("%d",(testResult.result.skipCount))
testDuration = String.format("%.2f",(testResult.result.duration ))
}
workspace = build.getEnvVars()["WORKSPACE"]
buildName = build.getEnvVars()["JOB_NAME"]
BUILD_STATUS = build.getEnvVars()["BUILD_STATUS"]
BUILD_URL = build.getEnvVars()["BUILD_URL"]
testResult1 = hudson.tasks.junit.TestResult
testResult2 = build.getAction(hudson.tasks.junit.TestResultAction.class)
caseResult = hudson.tasks.junit.CaseResult
rooturl = manager.hudson.rootUrl
} catch(Exception ex) {
rf << "exception accessing build.testResultAction object.";
//rf << ex;
}
// in groovy the write RE-creates the file, rf << "whatever" is used to append.
rf.write "<html><head><title>testreport.groovy #$buildNumber $buildName</title></head><body>"
rf << "Summary test report <br><br>\n\
<b>TEST RESULT:</b> $testCount total, <b>$testPassed pass</b>, <b>$testFailed fail</b>, $testSkipped skip.<br>\n\
Workspace : $workspace<br>\n\
Project Name : $buildName $buildNumHash<br><br>\n\
"
if (build) {
rf << """<!-- GENERAL INFO -->\n\
\n\
<TABLE>\n\
<TR><TD align=\"right\">\n\
<j:choose>\n\
<j:when test=\"${build.result=='SUCCESS'}\">\n\
<IMG SRC=\"${rooturl}static/e59dfe28/images/32x32/blue.gif\" />\n\
</j:when>\n\
<j:when test=\"${build.result=='FAILURE'}\">\n\
<IMG SRC=\"${rooturl}static/e59dfe28/images/32x32/red.gif\" />\n\
</j:when>\n\
<j:otherwise>\n\
<IMG SRC=\"${rooturl}static/e59dfe28/images/32x32/yellow.gif\" />\n\
</j:otherwise>\n\
</j:choose>\n\
</TD><TD valign='center'><B style='font-size: 200%;'>BUILD ${build.result}</B></TD></TR>\n\
<TR><TD>Build URL</TD><TD>${rooturl}${build.url}</TD></TR>\n\
<TR><TD>Project:</TD><TD>${buildName}</TD></TR>\n\
<TR><TD>Date of build:</TD><TD>${buildTimeString}</TD></TR>\n\
<TR><TD>Build duration:</TD><TD>${build.durationString}</TD></TR>\n\
<TR><TD>Test duration:</TD><TD>${testDuration}</TD></TR>\n\
</TABLE>\n\
<BR/>\n\
"""
}
if(!testResult) {
rf << "<br>No test result<br>"
rf << "</body></html>"
return ("No test result")
}
def junitResultList = [];
junitResultList.add(testResult.getResult())
if (junitResultList.size() > 0) {
rf << "<br>test result from build.testResultAction"
} else {
junitResultList.add(testResult2.getResult())
if (junitResultList.size() > 0) {
rf << "<br>test result from build.getAction"
} else {
rf << "<br>No results in 'testResult2'<br>\n"
junitResultList.add(testResult1.getResult())
}
}
//rf << "<br>DEBUG" + junitResultList.size() + " test items"
// API: http://hudson-ci.org/javadoc/hudson/tasks/junit/PackageResult.html
rf << "<!-- JUnit TEMPLATE: all tests PASS FAIL SKIP -->\n"
if (junitResultList.size() > 0) {
rf << '<TABLE width="100%">\n'
rf << "<TR><TD class='bg1' colspan='2'><B>${junitResultList.first().displayName}</B></TD></TR>\n"
junitResultList.each { junitResult ->
junitResult.getChildren().each { packageResult ->
rf << "<TR><TD class='bg2' colspan='2'> <B>TEST SUITE: ${packageResult.getName()} Failed: ${packageResult.getFailCount()} test(s), Passed: ${packageResult.getPassCount()} test(s)</B>, Skipped: ${packageResult.getSkipCount()} test(s), Total: ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()} test(s)</TD></TR>\n"
packageResult.getChildren().each { suite ->
suite.getChildren().each { test ->
def colour = "lightgreen"
def highlight1=""
def highlight2=""
RESULT = test.getStatus().name() // FAILED or PASSED or SKIPPED (.name() not .value)
// hudson.tasks.junit.CaseResult.Status.FAILED
if (RESULT == "FAILED" || RESULT == "REGRESSION") {
colour = "#ffcccc"
highlight1="<B>"
highlight2="</B>"
}
if (RESULT == "SKIPPED") { colour = "#ffffb3" }
rf << "<TR bgcolor='${colour}'><TD class='test' colspan='2'>${highlight1}<li>${RESULT}: ${test.getFullName()} </li>${highlight2}</TD></TR>\n"
}
}
}
}
rf << '</TABLE><BR/>\n'
}
rf << "testreport.groovy</body></html>\n"
I found it! The answer is call the undocumented test.getSkippedMessage() method. It is visible in the source code.
py.test writes skip message into junit xml.
Tag like this inside the test result: <skipped message="the skipped message">
That message can be a custom message from message in skip() call, or in case of xfail or xpass the message is set by pytest to "expected test failure" or "xfail-marked test passes unexpectedly".
jenkins junit plugin reads the junit xml.
The message is available through the API here:
class CaseResult getSkippedMessage()
see
https://github.com/jenkinsci/junit-plugin/blob/master/src/main/java/hudson/tasks/junit/CaseResult.java
Although it is not documented here:
http://hudson-ci.org/javadoc/hudson/tasks/junit/CaseResult.html
Change this part of code above from:
if (RESULT == "SKIPPED") { colour = "#ffffb3" }
to:
def moremessage1 = "";
.
.
.
if (RESULT == "SKIPPED") {
colour = "#ffffb3"
moremessage1 += "<br>test.getSkippedMessage():" + test.getSkippedMessage() + "</br>"
}
rf << "<TR bgcolor='${colour}'><TD class='test' colspan='2'>${highlight1}<li>${RESULT}: ${test.getFullName()} ${moremessage1}</li>${highlight2}</TD></TR>\n"
more test code useful when experimenting with this API:
if (RESULT == "SKIPPED") {
colour = "#ffffb3"
moremessage1 += "<br>test.getSkippedMessage():" + test.getSkippedMessage() + "</br>"
moremessage1 += "<br>test.getStatus().getMessage():" + test.getStatus().getMessage() + "</br>"
moremessage1 += "<br>test.getTitle():" + test.getTitle() + "</br>"
moremessage1 += "<br>test.getStdout():" + test.getStdout() + "</br>"
moremessage1 += "<br>test.getStderr():" + test.getStderr() + "</br>"
moremessage1 += "<br>test.getErrorDetails():" + test.getErrorDetails() + "</br>"
moremessage1 += "<br>test.getErrorStackTrace():" + test.getErrorStackTrace() + "</br>"
moremessage1 += "<br>test.getName():" + test.getName() + "</br>"
moremessage1 += "<br>test.getSafeName():" + test.getSafeName() + "</br>"
moremessage1 += "<br>test.getSimpleName():" + test.getSimpleName() + "</br>"
moremessage1 += "<br>test.getFullName():" + test.getFullName() + "</br>"
moremessage1 += "<br>test.getClassName():" + test.getClassName() + "</br>"
moremessage1 += "<br>test.getDisplayName():" + test.getDisplayName() + "</br>"
moremessage1 += "<br>test.getPackageName():" + test.getPackageName() + "</br>"

QBOv3 XML Validation Fault 2500 (Invalid Reference Id )

I'm trying to create a test invoice at quickbooks using quickbooks-ruby gem. Note I have a test account at QB which doesn't have anything: invoice, customer, etc. It's a new account created only for testing purpose. So here is my code:
service = Quickbooks::Service::Invoice.new
service.company_id = current_user.company_id
service.access_token = create_consumer
qb_invoice = Quickbooks::Model::Invoice.new
qb_invoice.customer_id = 123
line_item = Quickbooks::Model::InvoiceLineItem.new
line_item.amount = 100
line_item.sales_item! do |detail|
detail.unit_price = 100
detail.quantity = 1
detail.item_id = 1
end
qb_invoice.line_items << line_item
res = service.create qb_invoice
p res.id #exception!
def create_consumer
OAuth::AccessToken.new(.....)
end
Request:
METHOD = post
RESOURCE = https://qb.sbfinance.intuit.com/v3/company/fdsfdsfdsfds123/invoice
<?xml version="1.0" encoding="utf-8"?>
<Invoice xmlns="http://schema.intuit.com/finance/v3" sparse="false">
<Line>
<Amount>100.0</Amount>
<DetailType>SalesItemLineDetail</DetailType>
<SalesItemLineDetail>
<ItemRef>1</ItemRef>
<UnitPrice>100.0</UnitPrice>
<RatePercent>0.0</RatePercent>
<Qty>1.0</Qty>
</SalesItemLineDetail>
</Line>
<CustomerRef>123</CustomerRef>
<TotalAmt>0.0</TotalAmt>
<Balance>0.0</Balance>
<Deposit>0.0</Deposit>
</Invoice>
and response with the error:
RESPONSE CODE = 400
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IntuitResponse xmlns="http://schema.intuit.com/finance/v3" time="2014-03-06T19:30:49.168-08:00">
<Fault type="ValidationFault">
<Error code="2500" element="">
<Message>Invalid Reference Id</Message>
<Detail>Invalid Reference Id : Something you're trying to use has been deleted. Check the fields with accounts, customers, items, vendors or employees.
</Detail>
</Error>
</Fault>
</IntuitResponse>
Could it be because a customer with id = 123 doesn't exist? If not, what's the cause then?
Please check if you have a customer(ID-123) and Item(Id-1) exist in your account.
If not then create these two entries using apiexplorer/code and use the corresponding object IDs.
ApiExplorer - https://developer.intuit.com/apiexplorer?apiname=V3QBO
EntityRef - https://developer.intuit.com/docs/0025_quickbooksapi/0050_data_services/030_entity_services_reference
ApiExplorer -
Ref - https://developer.intuit.com/docs/0025_quickbooksapi/0010_getting_started/0015_firstrequest
Thanks

XPath Nested Nodes

I need to loop and get the updates that belong to each lot, but when I use xmldoc.xpath("//update") it just gives me all of the updates even if not nested into the lot. How can I get the updates that are nested in to the selected lot only?
lots = xmldoc.xpath("//lot")
lots.each do |lot|
#lot = Lot.new
#lot.legacy_id = lot.at("legacy_id").text
#lot.event = #event
#lot.group = lot.at("group").text
#lot.number = lot.at("number").text
#lot.title = lot.at("title").text
#lot.description = lot.at("description").text
#lot.price = lot.at("price").text
#lot.start_at = lot.at("start_at").text
#lot.end_at = lot.at("end_at").text
#lot.position = lot.at("position").text
#lot.notes = lot.at("notes").text
#lot.save
updates = xmldoc.xpath("//update")
updates.each do |update|
#lot_update = LotUpdate.new
#lot_update.save
end
end
XML:
<?xml version="1.0" encoding="UTF-8" ?>
<event>
<legacy_id>54321</legacy_id>
<lots>
<lot>
<legacy_id>12345</legacy_id>
<number>1</number>
<title>Big Cow</title>
<description>A big cow</description>
<position>1</position>
<price>500</price>
<start_at>2013-02-15 10:00:00</start_at>
<end_at>2013-02-15 12:00:00</end_at>
<group>1</group>
</lot>
</lots>
<lots>
<lot>
<legacy_id>12346</legacy_id>
<number>1</number>
<title>Small Cow</title>
<description>A small cow</description>
<position>1</position>
<price>500</price>
</lot>
</lots>
</event>
You want lot.xpath('.//update').

Grails paginate usage

What is wrong with this code, because im getting all the results returning to the view, which takes me too much to load. I want it to return only 5 per page.
Controller:
{
def channel2 = Channel2.list(params)
//def prog = Programmation.list()
def prog
def progs = [:]
def temp
channel2.each{
Programmation p = Programmation.withCriteria {
eq('prog_channel', it)
'between'('prog_start', new Date(), new Date() +1)
}
progs.put(it.id, p)
}
[channel: channel2, program: progs]
}
GSP
<g:render id="" template="/layouts/canais"/>
<g:paginate next="Forward" prev="Back"
maxsteps="0" max="3" controller="teste"
action="myProgramms_canais"
total="${tv_megazineplus.Channel2.count()}" />
I cann't figure it out. I followed Grails helpPage, it should be working.
Solution: The first time the that action is called, it loads all channels because the params.max is set to null. To fix that, just use:
def offset
if(!params.offset){
offset = 0
}
def channel2 = Channel2.list(max:5, offset: offset)

Resources