def retrieveFailedTests()

in jenkins-pipeline-shared-libraries/vars/util.groovy [262:318]


def retrieveFailedTests(String buildUrl = "${BUILD_URL}") {
    def testResults = retrieveTestResults(buildUrl)

    def allCases = []
    testResults.suites?.each { testSuite ->
        allCases.addAll(testSuite.cases)
    }

    def failedTests = []
    testResults.suites?.each { testSuite ->
        testSuite.cases?.each { testCase ->
            if (!['PASSED', 'SKIPPED', 'FIXED'].contains(testCase.status)) {
                def failedTest = [:]
                
                boolean hasSameNameCases = allCases.findAll { it.name == testCase.name && it.className == testCase.className }.size() > 1

                failedTest.status = testCase.status

                // Retrieve class name
                fullClassName = testCase.className
                int lastIndexOf = fullClassName.lastIndexOf('.')
                packageName = fullClassName.substring(0, lastIndexOf)
                className = fullClassName.substring(lastIndexOf + 1)

                failedTest.name = testCase.name
                failedTest.packageName = packageName
                failedTest.className = className
                failedTest.enclosingBlockNames = testSuite.enclosingBlockNames?.reverse()?.join(' / ')

                failedTest.fullName = "${packageName}.${className}.${failedTest.name}"
                // If other cases have the same className / name, Jenkins uses the enclosingBlockNames for the URL distinction
                if (hasSameNameCases && testSuite.enclosingBlockNames) {
                    failedTest.fullName = "${testSuite.enclosingBlockNames.reverse().join(' / ')} / ${failedTest.fullName}"
                }

                // Construct test url
                String urlLeaf = ''
                // If other cases have the same className / name, Jenkins uses the enclosingBlockNames for the URL distinction
                if (hasSameNameCases && testSuite.enclosingBlockNames) {
                    urlLeaf += testSuite.enclosingBlockNames.reverse().join('___')
                }
                urlLeaf += urlLeaf ? '___' : urlLeaf
                urlLeaf += "${failedTest.name == "(?)" ? "___" : failedTest.name}/"
                urlLeaf = urlLeaf.replaceAll(' ', '_')
                                    .replaceAll('&', '_')
                                    .replaceAll('-', '_')
                failedTest.url = "${buildUrl}testReport/${packageName}/${className}/${urlLeaf}"

                failedTest.details = [null, 'null'].contains(testCase.errorDetails) ? '' : testCase.errorDetails
                failedTest.stacktrace = [null, 'null'].contains(testCase.errorStackTrace) ? '' : testCase.errorStackTrace
                failedTests.add(failedTest)
            }
        }
    }

    return failedTests
}