Как получить доступ к подсчетам Junit в проекте Jenkins Pipeline

Я только что начал с Дженкинса

Мой проект фристайла, используемый для отчета о результатах тестов JUnit в Slack, как это

MyJenkinsFreestyle - #79 Unstable after 4 min 59 sec (Open)
Test Status:
    Passed: 2482, Failed: 13, Skipped: 62

Теперь я переместил один и тот же проект в конвейер, и все хорошо, за исключением того, что Slack-уведомления не имеют статуса проверки

done MyPipelineProject #68 UNSTABLE

Я понимаю, что мне нужно создать сообщение для отправки в Slack, и я уже сделал это выше.

Единственная проблема заключается в том, как я могу прочитать статус теста - пройденный счет, неудачный счет и т.д. Это называется "тестовое резюме" в Jenkins slack-plugin commit, и вот скриншот testsummaryimage

Итак, как мне получить доступ к списку/деталям Junit tests в проекте Jenkins Pipeline? - чтобы они сообщались в уведомлениях.

UPDATE: В проекте Freestyle само уведомление "Slack" имеет "сводку теста", и нет возможности выбрать (или нет) для сводки теста.

В проекте Pipeline моя команда "junit" для "Опубликовать результаты теста JUnit" перед отправкой уведомлений Slack.

Итак, в коде эти строки выглядят так (это последние строки последнего этапа):

bat runtests.bat
junit 'junitreport/xml/TEST*.xml'
slackSend channel: '#testschannel', color: 'normal', message: "done ${env.JOB_NAME} ${env.BUILD_NUMBER} (<${env.BUILD_URL}|Open>)";

Ответ 1

Из этой презентации Cloudbees я обнаружил, что это возможно с помощью объекта "build". Имеет такой код

def testResult = build.testResultAction
def total = testResult.totalCount

Но currentBuild не предоставляет доступ к testResultAction.

Поэтому продолжил поиск и нашел этот пост "реагировать на неудачные тесты в конвейерном скрипте". Там Роберт Санделл дал "про чаевые"

Совет, требующий некоторого "пользовательского белого списка":

AbstractTestResultAction testResultAction =  currentBuild.rawBuild.getAction(AbstractTestResultAction.class)
if (testResultAction != null) {
    echo "Tests: ${testResultAction.failCount} / ${testResultAction.failureDiffString} failures of ${testResultAction.totalCount}.\n\n" 
}

Это работало как обаяние - просто я должен был снять флажок "Groovy sandbox". Теперь у меня есть это в журнале сборки

Tests: 11  / ±0 failures of 2624

Теперь я буду использовать это, чтобы подготовить строку для уведомления о результатах теста.


ОБНОВИТЬ:

Наконец, функция, которую я использовал, чтобы получить вывод, подобный следующему (обратите внимание, что "diff diff" после неудачных тестов очень полезно)

Test Status:
  Passed: 2628, Failed: 6  / ±0, Skipped: 0

Является ли следующее:

import hudson.tasks.test.AbstractTestResultAction

@NonCPS
def testStatuses() {
    def testStatus = ""
    AbstractTestResultAction testResultAction = currentBuild.rawBuild.getAction(AbstractTestResultAction.class)
    if (testResultAction != null) {
        def total = testResultAction.totalCount
        def failed = testResultAction.failCount
        def skipped = testResultAction.skipCount
        def passed = total - failed - skipped
        testStatus = "Test Status:\n  Passed: ${passed}, Failed: ${failed} ${testResultAction.failureDiffString}, Skipped: ${skipped}"

        if (failed == 0) {
            currentBuild.result = 'SUCCESS'
        }
    }
    return testStatus
}

ОБНОВЛЕНИЕ 2018-04-19

Обратите внимание на то, что вышеупомянутые требуют ручного "белого списка" используемых методов. Вот как вы можете внести в белый список все методы за один раз

Обновите белый список вручную...

Выход из Дженкинс

Создайте/обновите% USERPROFILE%.jenkins\scriptApproval.xml со следующим содержимым

<?xml version='1.0' encoding='UTF-8'?>
<scriptApproval plugin="[email protected]">
<approvedScriptHashes>
</approvedScriptHashes>
<approvedSignatures>
<string>method hudson.model.Actionable getAction java.lang.Class</string>
<string>method hudson.model.Cause getShortDescription</string>
<string>method hudson.model.Run getCauses</string>
<string>method hudson.tasks.test.AbstractTestResultAction getFailCount</string>
<string>method hudson.tasks.test.AbstractTestResultAction getFailureDiffString</string>
<string>method hudson.tasks.test.AbstractTestResultAction getSkipCount</string>
<string>method hudson.tasks.test.AbstractTestResultAction getTotalCount</string>
<string>method org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper getRawBuild</string>
</approvedSignatures>
<aclApprovedSignatures/>
<approvedClasspathEntries/>
<pendingScripts/>
<pendingSignatures/>
<pendingClasspathEntries/>
</scriptApproval>
  • Перезапустите Дженкинс
  • и затем убедитесь, что в "Утверждении сценария" утверждены вышеуказанные записи
  • ПРИМЕЧАНИЕ: это важно. Так что, если файл scriptApproval уже существует, тогда вам, как правило, необходимо убедиться в содержимом тега.

Ответ 2

Чтобы расширить ответ @vikramsjn, вот что я использую, чтобы получить сводку тестов в моем Jenkinsfile:

import hudson.tasks.test.AbstractTestResultAction
import hudson.model.Actionable

@NonCPS
def getTestSummary = { ->
    def testResultAction = currentBuild.rawBuild.getAction(AbstractTestResultAction.class)
    def summary = ""

    if (testResultAction != null) {
        def total = testResultAction.getTotalCount()
        def failed = testResultAction.getFailCount()
        def skipped = testResultAction.getSkipCount()

        summary = "Test results:\n\t"
        summary = summary + ("Passed: " + (total - failed - skipped))
        summary = summary + (", Failed: " + failed)
        summary = summary + (", Skipped: " + skipped)
    } else {
        summary = "No tests found"
    }
    return summary
}

Затем я использую этот метод для создания экземпляра моей переменной testSummary:

def testSummary = getTestSummary()

Это вернет что-то похожее на:

"Test results:
     Passed: 123, Failed: 0, Skipped: 0"

Ответ 3

Прежде всего, спасибо за ответы выше. Они сэкономили мне много времени, я использовал предложенное решение в своем конвейере. Я, однако, не использовал "белый список", и он отлично работает. Я использую разделяемые библиотеки для конвейера Jenkins, и вот часть этой разделяемой библиотеки с конвейером и использованием методов для получения счетчиков:

import hudson.model.*
import jenkins.model.*
import hudson.tasks.test.AbstractTestResultAction

def call(Closure body) {
    ...

    def emailTestReport = ""

    pipeline {
        ...

        stages{
            stage('Test'){
                ...
                post {
                    always {
                        junit 'tests.xml'

                        script {
                            AbstractTestResultAction testResultAction =  currentBuild.rawBuild.getAction(AbstractTestResultAction.class)
                            if (testResultAction != null) {
                                def totalNumberOfTests = testResultAction.totalCount
                                def failedNumberOfTests = testResultAction.failCount
                                def failedDiff = testResultAction.failureDiffString
                                def skippedNumberOfTests = testResultAction.skipCount
                                def passedNumberOfTests = totalNumberOfTests - failedNumberOfTests - skippedNumberOfTests
                                emailTestReport = "Tests Report:\n Passed: ${passedNumberOfTests}; Failed: ${failedNumberOfTests} ${failedDiff}; Skipped: ${skippedNumberOfTests}  out of ${totalNumberOfTests} "
                            }
                        }

                        mail to: '[email protected]',
                        subject: "Tests are finished: ${currentBuild.fullDisplayName}",
                        body: "Tests are finished  ${env.BUILD_URL}\n  Test Report: ${emailTestReport} "
                    }

                }
            }
        }
    }
}

ps Если я создаю emailTestRepot как локальную переменную внутри скрипта "section", я получаю следующее исключение:

an exception which occurred:
    in field locals
    in field parent
    in field caller
    in field e
    in field program
    in field threads
    in object [email protected]
Caused: java.io.NotSerializableException: hudson.tasks.junit.TestResultAction
...

Я много пытался исправить это исключение java.io.NotSerializableException. Как я понял, мне нужно было использовать "белый список" для предотвращения исключения NotSerializableException. Но я действительно не хотел этого делать, и когда я переместил "def emailTestReport" из конвейера, он работал просто отлично.