web-dev-qa-db-fra.com

Comment accéder aux comptes de tests Junit dans le projet de pipeline Jenkins

Je viens de commencer avec Jenkins

Mon projet de style libre avait l'habitude de rapporter les résultats des tests JUnit dans Slack comme ceci

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

Maintenant, je suis passé au même projet pipeline, et tout va bien sauf que les notifications Slack n'ont pas de statut de test

done MyPipelineProject #68 UNSTABLE

Je comprends que je dois construire le message à envoyer à Slack, et je l’ai fait plus haut pour le moment.

Le seul problème est de savoir comment lire l'état du test - le nombre de tests passés, le nombre d'échecs, etc. Ceci est appelé "résumé du test" dans Jenkins slack-plugin commit , et voici la capture d'écran  testsummaryimage

Alors, comment puis-je accéder au nombre/détails de tests Junit dans le projet de pipeline Jenkins? - afin que ceux-ci soient signalés dans les notifications.

UPDATE: Dans le projet Freestyle, la notification Slack elle-même contient le "résumé du test" et il n'y a pas d'option pour opter (ou non) pour le résumé du test.

Dans le projet Pipeline, ma commande "junit" pour "Publier les résultats du test JUnit" est avant d'envoyer une notification Slack.

Donc, dans le code, ces lignes ressemblent à ceci (ce sont les dernières lignes de la dernière étape):

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>)";
16
vikramsjn

De cette présentation de Cloudbees, j’ai trouvé qu’il devrait être possible via l’objet "build" . Il a un code comme

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

Mais currentBuild ne donne pas accès à testResultAction.

Alors continua à chercher et trouvai cet article "réagit aux tests ayant échoué dans le script de pipeline" . Là, Robert Sandell a donné "conseil pro"

Astuce Pro, nécessite une "liste blanche personnalisée":

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

Cela a fonctionné comme un charme - juste que je devais désélectionner la case à cocher "Groovy sandbox" . Maintenant, je les ai dans le journal de construction

Tests: 11  / ±0 failures of 2624

Maintenant, je vais utiliser ceci pour préparer une chaîne à notifier avec des résultats de test.


METTRE À JOUR:

Enfin, la fonction que j’utilisais pour obtenir une sortie comme celle-ci est la suivante .__ (Notez que le "test de défaillance" après des tests ayant échoué est très utile)

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

Est le suivant:

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
}

UPDATE 2018-04-19

Notez que ce qui précède nécessite une "liste blanche" manuelle des méthodes utilisées. Voici comment vous pouvez ajouter toutes les méthodes en une seule fois.

Mettre à jour manuellement la liste blanche ...

Sortie Jenkins

Créez/mettez à jour% USERPROFILE% .jenkins\scriptApproval.xml avec le contenu suivant

<?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>
  • Redémarrer Jenkins
  • puis vérifiez que "l'entrée de script" a les entrées ci-dessus approuvées
  • NOTE: C'est ce qui est important. Donc, si le fichier scriptApproval existe déjà, vous devrez généralement vérifier le contenu de la balise.
26
vikramsjn

Pour développer la réponse de @ vikramsjn, voici ce que j'utilise pour obtenir le résumé du test dans mon 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
}

J'utilise ensuite cette méthode pour instancier ma variable testSummary:

def testSummary = getTestSummary()

Cela retournera quelque chose de similaire à:

"Test results:
     Passed: 123, Failed: 0, Skipped: 0"
7
Christopher Rung

Tout d'abord, merci pour les réponses ci-dessus. Ils m'ont fait gagner beaucoup de temps, j'ai utilisé la solution proposée dans mon pipeline. Cependant, je n'ai pas utilisé "liste blanche" et cela fonctionne très bien . J'utilise des bibliothèques partagées pour le pipeline 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} "
                    }

                }
            }
        }
    }
}

p.s. Si je crée emailTestRepot en tant que variable locale dans le script "section", j'obtiens la prochaine exception:

an exception which occurred:
    in field locals
    in field parent
    in field caller
    in field e
    in field program
    in field threads
    in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@11cd92de
Caused: Java.io.NotSerializableException: hudson.tasks.junit.TestResultAction
...

J'ai eu beaucoup de mal à essayer de corriger cette exception Java.io.NotSerializableException. Si j'ai bien compris, je devais utiliser la "liste blanche" pour empêcher NotSerializableException. Mais je ne voulais vraiment pas le faire et quand j'ai déplacé "def emailTestReport" hors pipeline, cela fonctionnait parfaitement.

1
Arthur Shakhlamjian