Jenkins scripted pipeline does not fetch the test result if unit test fails

自古美人都是妖i 提交于 2019-12-11 15:17:36

问题


I have gradle based java projects with junit tests which I'm building CI jobs for. I was successfully able to integrate slack with Jenkins using slack Slack Notification plugin.

Jenkins Version : 2.173
Slack Notification version : 2.20

The jenkins CI is a scripted pipeline, which has the below code:


stage('Test') {
        def slackHelper = new com.xyz.jenkins.libraries.SlackNotifier(env)
        try {
            sh "./gradlew test"
            junit 'build/test-results/test/*.xml'
        } finally {
            AbstractTestResultAction testResultAction =  currentBuild.rawBuild.getAction(AbstractTestResultAction.class)

            slackHelper.getTestStatuses(currentBuild)
            slackSend(channel: '#ci-cd', attachments: slackHelper.buildUnitTestSlackNotificationMessage())
        }
    }

SlackNotifier is a library which has the below code:

/**
 * Calculates test result as a string
 * @param currentBuild : jenkins object, should be passed from jenkins pipeline script
 * @return the final test result as a string
 */
@NonCPS
def getTestStatuses(currentBuild) {
    final AbstractTestResultAction testResultAction = currentBuild.rawBuild.getAction(AbstractTestResultAction.class)
    if (testResultAction != null) {
        this.total = testResultAction.totalCount
        this.failed = testResultAction.failCount
        this.skipped = testResultAction.skipCount
        this.passed = total - failed - skipped
    }
}

buildUnitTestSlackNotificationMessage does this in the same class:

def buildUnitTestSlackNotificationMessage() {
        final JSONObject unitTestResult = new JSONObject()
        unitTestResult.put("fallback", this.jenkinsEnvironment.JOB_NAME + "with build#" + this.jenkinsEnvironment.BUILD_NUMBER + "finish with unit test result : Passed: " + this.passed + " | Failed: " + this.failed + " | Skipped: " + this.skipped )
        unitTestResult.put("color", this.getUnitTestReportColor())
        unitTestResult.put("pretext", "Message from CI job: " + this.jenkinsEnvironment.JOB_NAME + "#" + this.jenkinsEnvironment.BUILD_NUMBER)
        unitTestResult.put("title", "BuildLog")
        unitTestResult.put("title_link", "<<<JenkinsHost>>>" + this.jenkinsEnvironment.JOB_NAME + "/" + this.jenkinsEnvironment.BUILD_NUMBER  + "/console")
        unitTestResult.put("text", "Passed: " + this.passed +  " | Failed: " + this.failed + " | Skipped: " + this.skipped)
        unitTestResult.put("image_url", this.getLogoURL())
        this.attachments.add(unitTestResult)
        return this.attachments.toString()
    }

All is well when all the tests pass. But when tests fail I get the below notification:

Message from CI job: <<<JobName>>>#47
BuildLog
Passed: null | Failed: null | Skipped: null

It turns out testResultAction is null when any unit tests fail here.

And I'm unable to come to the bottom of this. Please help.


回答1:


I got the answer in reddit, credit goes to : /u/Bodumin

And here is the root cause, I'm quoting him here :

Move the junit step into the finally. What's likely happening is that test returns a non 0 (error) status so it fails it of the try.

So, the scripted pipeline looks like below:

stage('Test') {
        def slackHelper = new com.xyz.jenkins.libraries.SlackNotifier(env)
        try {
            sh "./gradlew test"
        } finally {
            junit 'build/test-results/test/*.xml'
            AbstractTestResultAction testResultAction =  currentBuild.rawBuild.getAction(AbstractTestResultAction.class)

            slackHelper.getTestStatuses(currentBuild)
            slackSend(channel: '#ci-cd', attachments: slackHelper.buildUnitTestSlackNotificationMessage())
        }
    }


来源:https://stackoverflow.com/questions/55699031/jenkins-scripted-pipeline-does-not-fetch-the-test-result-if-unit-test-fails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!