In my pipeline, I have two lists and want to compare it and print output accordingly
1- println abc
[aaa, bbb, ccc]
2- println xyz
[bbb, ccc]
I need to print the output to a file like:
aaa not present in xyz
bbb present
ccc preset
Code I tried:
def test []
test = abc - xyz
println test
def abc = ['aaa', 'bbb', 'ccc']
def xyz = ['bbb', 'ccc']
//simple
println 'present in xyz: ' + abc.intersect(xyz).join(', ')
println 'not present in xyz: ' + abc.minus(xyz).join(', ')
//with for-each
for(i in abc){
if(i in xyz) println "present in xyz: $i"
else println "not present in xyz: $i"
}
You can try something along those lines:
abc.each{valueOne ->
doesValueExist = false
xyz.each{ valueTwo->
if(valueOne.equals(valueTwo}{
doesValueExist = true
}
}
if(doesValueExist){
echo "${valueOne} is present"
} else {
echo "${valueOne} is not present"
}
}
Related
This is the output I got:
"Successfully created scratch org: oopopoooppooop, username: test+color#example.com"
when I run the following script:
echo "1. Creating Scratch Org"
def orgStatus = bat returnStdout: true, script: "sfdx force:org:create --definitionfile ${PROJECT_SCRATCH_PATH} --durationdays 30 --setalias ${SCRATCH_ORG_NAME} -v DevHub "
if (!orgStatus.contains("Successfully created scratch org")) {
error "Scratch Org creation failed"
} else {
echo orgStatus
}
Now I need to extract scratch org ID and username from the output separately and store it.
You can use a regular expression:
def regEx = 'Successfully created scratch org: (.*?), username: (.*)'
def match = orgStatus =~ regEx
if( match ) {
println "ID: " + match[0][1]
println "username: " + match[0][2]
}
Here the operator =~ applies the regular expression to the input and the result is stored in match.
Live Demo
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>"
I am trying to implement following in GROOVY script but getting errors:
Read contents of an HTML file in an array and then grep for something in that array.
def file1 = new File("/path/to/the/file/xyz.html");
def lines = file1.readLines()
if ((-e "/path/to/the/file/xyz.html") and (!(grep /jira.bugtracker.com/, lines))
{
println (" the changes are present\n");
exit 0;
}
else
{
println (" the changes are not present\n");
exit 1;
}
Please review the code and suggest the correct method.
def file1 = new File("/path/to/the/file/xyz.html" )
def lines = file1.readLines()
def found = lines.find{ line-> line =~ /jira.bugtracker.com/ }
println ("the changes are ${ found ? '' : 'not ' }present")
return found ? 0 : 1
you can try like this.
if ( new File("/path/to/the/file/xyz.html").text?.contains("jira.bugtracker.com")){
println (" the changes are present\n");
} else {
println (" the changes are not present\n");
}
Using spock to unit test a comand object .. I have a line in the command object ..
some code ..
} else {
if ((val && obj.part) && obj.transactionType.transactionIsATransfer()) {
println "obj.part .. class is ${obj.part.getClass()} .. serial is ${val.getClass()}"
if(! isAValidPartSerialCombo(obj.part,val)) <-- line 79
return 'com.myStuff.TransactionDetailCommand.serialReference.not.for.part'
}
..
def isAValidPartSerialCombo {part, serialReference ->
return InventoryMaster.hasPartandSerial(part,serialReference)
}
I have a unit test where I mock out the dependency
def obj = new TransactionDetailCommand(transactionType: new TransactionType(type: 'Transfer', requireSerial: true),
serialReference: 'AAA', part: new Part(partNumber: 'AAA'))
obj.metaClass.isAValidPartSerialCombo = {a,b -> false}
and: "we try to validate the transaction "
obj.validate()
then: "we get an error on the transaction for the 'serialReference' property"
obj.errors['serialReference']
which is giving me an error ..
java.lang.IllegalArgumentException: object is not an instance of declaring class
at com.vantec.TransactionDetailCommand._clinit__closure1_closure7(TransactionDetailCommand.groovy:90)
at grails.test.MockUtils.addValidateMethod_closure87_closure114(MockUtils.groovy:1035)
at grails.test.MockUtils.addValidateMethod_closure87(MockUtils.groovy:1031)
at grails.test.MockUtils.addValidateMethod_closure88(MockUtils.groovy:1065)
at com.myStuff.transaction.TransactionDetailCommandSpec.Ensure that for issues / transfer transactions then serial/part numbers are required to match .. (TransactionDetailCommandSpec.groovy:79)
However if I create a separate dummy test it works without a problem ..
def "A simple test .. "(){
when:
def obj = new TransactionDetailCommand()
obj.metaClass.isAValidPartSerialCombo = {a,b -> false}
then: 'we get a false ..'
!obj.isAValidPartSerialCombo(new Part(),"AAA")
}
Can anyone shed any light ??
Thanks
Complete test ...
def "Ensure that for issues / transfer transactions then serial/part numbers are required to match .. "(){
when: "The transaction type indicates a transfer and we supply a serial number and a part .."
def obj = new TransactionDetailCommand(transactionType: new TransactionType(type: 'Transfer', requireSerial: true),
serialReference: '12345', part: new Part(partNumber: 'PartA'))
obj.metaClass.isAValidPartSerialCombo = {a,b -> false}
and: "we try to validate the transaction "
obj.validate()
then: "we get an error on the transaction for the 'serialReference' property"
obj.errors['serialReference']
and: "the error is the correct one .."
'com.myStuff.TransactionDetailCommand.serialReference.not.for.part' == obj.errors['serialReference']
}
and the constraint i'm testing ..
serialReference nullable: true, validator: { val, obj ->
println "One .. "
if ((val == null || val.toString().isEmpty()) && obj.transactionType.requireSerial) {
println "Two .. "
return 'com.myStuff.TransactionDetailCommand.serialReference.required'
} else {
println "Three .. "
if ((val && obj.part) && obj.transactionType.transactionIsATransfer()) {
println "Four ..."
if(! isAValidPartSerialCombo(obj.part, val)){
println("Five .. ")
return 'com.myStuff.TransactionDetailCommand.serialReference.not.for.part'
}
}
}
return 'oops'
}
def isAValidPartSerialCombo = {part, serialReference ->
println "Six .."
// return InventoryMaster.hasPartandSerial(part,serialReference)
return true
}
The println's are just so I can see where the code goes ..
Not sure about it, but it would be worthy to give a try to mock the instance of obj after the creation of the instance
mockDomain(TransactionDetailCommand, [obj])
Try to organise in that way your test:
def "Ensure that for issues / transfer transactions then serial/part numbers are required to match .. "(){
given: "The transaction type indicates a transfer and we supply a serial number and a part .."
def obj = new TransactionDetailCommand(transactionType: new TransactionType(type: 'Transfer', requireSerial: true),
serialReference: '12345', part: new Part(partNumber: 'PartA'))
obj.metaClass.isAValidPartSerialCombo = {a,b -> false}
when: "we try to validate the transaction "
obj.validate()
then: "we get an error on the transaction for the 'serialReference' property"
obj.errors['serialReference']
and: "the error is the correct one .."
'com.myStuff.TransactionDetailCommand.serialReference.not.for.part' == obj.errors['serialReference']
}
as the creation of the object and the metaprogramming are all set up actions.
i would like to create a query with the Criteria API in Grails (GORM).
The query will have to be something like this:
MyEntity.createCriteria().list{
assoc{
parent{
eq("code", val)
}
}
}
What i need is to build the nested closure dynamically from a String object. The String for the example above will be "assoc.parent.code" . I splitted the String by dot (by doing String.split("\\.") ) but i don't know how to construct the nested closures:
assoc{
parent{
eq("code", val)
}
}
dynamically based on the array of the splitted Strings above.
What about createAlias?. You could try something like this:
def path = "assoc.parent.code"
def split = path.split(/\./)
MyEntity.createCriteria().list {
// this will get you 'createAlias( assoc.parent, alias1 )'
createAlias split.take( split.size() - 1 ), "alias1"
// this will get you 'eq(alias1.code, userInput)'
eq "alias1.${split[-1]}", userInput
}
This snippet is not generic, but you get the idea.
Update
Not conventional, but you can build a string containing the code with the closures and evaluate it using GroovyShell:
assoc = 'assoc.parent.child.name'
split = assoc.split( /\./ )
path = split[-2..0] // will get us 'child.parent.assoc';
// we will build it from inside-out
def firstClosure = "{ eq '${split[-1]}', 'john doe' }"
def lastClosure = firstClosure
for (entity in path) {
def criteriaClosure = "{ ${entity} ${lastClosure} }"
lastClosure = criteriaClosure
}
assert lastClosure == "{ assoc { parent { child { eq 'name', 'john doe' } } } }"
def builtClosure = new GroovyShell().evaluate("return " + lastClosure)
assert builtClosure instanceof Closure
A more generic approach would be to metaClass String as below, and use it for any kind of separator
. | , - ~ and more.
String.metaClass.convertToClosureWithValue = {op, val ->
split = delegate.split(op) as List
if(split.size() == 1) {return "Cannot split string '$delegate' on '$op'"}
items = []
split.each{
if(it == split.last()){
items << "{ eq '$it', $val }"
split.indexOf(it).times{items.push("}")}
} else {
items << "{$it"
}
}
println items.join()
new GroovyShell().evaluate("return " + items.join())
}
assert "assoc.parent.child.name".convertToClosureWithValue(/\./, "John Doe") instanceof Closure
assert "assoc-parent-child-name".convertToClosureWithValue(/\-/, "Billy Bob") instanceof Closure
assert "assoc|parent|child|grandChild|name".convertToClosureWithValue(/\|/, "Max Payne") instanceof Closure
assert "assoc~parent~child~grandChild~name".convertToClosureWithValue('\\~', "Private Ryan") instanceof Closure
assert "assocparentchildname".convertToClosureWithValue(/\|/, "Captain Miller") == "Cannot split string 'assocparentchildname' on '\\|'"
//Print lines from items.join()
{assoc{parent{child{ eq 'name', John Doe }}}}
{assoc{parent{child{ eq 'name', Billy Bob }}}}
{assoc{parent{child{grandChild{ eq 'name', Max Payne }}}}}
{assoc{parent{child{grandChild{ eq 'name', Private Ryan }}}}}