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
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>)";
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>
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"
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.