Как я могу написать шаблон электронной почты Jenkins для отображения результатов теста, таких как стандартный отчет об испытаниях

Я изменил шаблон стандартного молочка, чтобы отобразить текущие результаты теста в таблице, однако я действительно хочу иметь возможность отображать различия, как показано на странице результатов теста Jenkins.

Например:

JUnit Tests: 0 failures (±0) , 1 skipped (+1)

Package               Duration   Fail  (diff)  Skip  (diff)  Total  (diff)
foo.bar.baz              89 ms      0      0     1       +1     5       +2

Ответ 1

Напишите шаблон Groovy для плагина Email Ext вместо шаблона Jelly. В шаблоне Groovy у вас будет доступ к объекту Build для вашей сборки. Затем вы можете вызвать getTestResultAction, чтобы получить AbstractTestResultAction для сборки, которую вы можете затем запрос на все, что вам нужно.

Вот ссылка на API основного модуля Jenkins. Пример шаблона Groovy для плагина Ext Email можно найти в $JENKINS_HOME/plugins/email-ext/WEB-INF/classes/hudson/plugins/emailext/templates/groovy-html.template. Более подробную информацию о Groovy шаблоне /script можно найти в Email Ext плагин документации.

Ответ 2

Если вы боретесь с тем, как получить доступ к нему через внутренний API (трудно знать и он существует ограничение всегда), есть еще один более гибкий способ сделать это.

Использование токена FILE вместо groovy template

  • используя script для доступа к вашим данным тестирования через Jenkins API, для вашего случая это похоже на http://jenkins.server/job/yourjob/lastCompletedBuild/testReport/api/xml и создать собственный html файл, например email.html в рабочей области
  • В форме Default Content в конфигурации электронной почты-ext, используя токен FILE, чтобы отправить электронное письмо непосредственно ${FILE, path="email.html"}

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

Он отлично работает для меня.

Ответ 3

Чтобы расширить этот ответ: Напишите шаблон Groovy для плагина Email Ext вместо шаблона Jelly. В редактируемом уведомлении по электронной почте

  • установить тип содержимого в "HTML" или "Оба HTML и обычный текст"
  • и включите Groovy script следующим образом:

    ${SCRIPT, template = "test.groovy" }

  • поместите Groovy script в шаблоны электронной почты домой, например. /Вар/Lib/Jenkins/электронная почта-шаблоны. см. ниже test.groovy.

В приведенном ниже примере каждый тест повторяется путем получения каждого из этих объектов: '' 'junitResult.getChildren()' ''. Если кто-то захочет итерации только неудавшихся тестов, тогда можно использовать junitResult.getFailedTests(). См. API hudson.tasks.junit.TestResult: http://hudson-ci.org/javadoc/hudson/tasks/junit/PackageResult.html также см. http://hudson-ci.org/javadoc/hudson/model/Build.html

Collection<ClassResult> getChildren()
List<CaseResult>    getFailedTests()

Пример/шаблон из email-ext-plugin можно увидеть здесь: https://github.com/jenkinsci/email-ext-plugin/blob/master/src/main/resources/hudson/plugins/emailext/templates/groovy-html.template

В этом примере показан итоговый результат теста и таблица результатов для каждого набора тестов и индивидуального теста. test.groovy:

<html>
<body>
<%

    import hudson.model.*

    def build = Thread.currentThread().executable
    def buildNumber = build.number
    def buildNumHash = build.getDisplayName()

    def testCount = "0"
    def testPassed = "0"
    def testFailed = "0"
    def testSkipped = "0"
    def buildDuration = "0"
    if(build.testResultAction) {
        def testResult = build.testResultAction
        testCount = String.format("%d",(testResult.totalCount))
        testPassed = String.format("%d",(testResult.result.passCount))
        testFailed = String.format("%d",(testResult.result.failCount))
        testSkipped = String.format("%d",(testResult.result.skipCount))
        testDuration = String.format("%.2f",(testResult.result.duration ))
    }

    def workspace = build.getEnvVars()["WORKSPACE"]
    def buildName = build.getEnvVars()["JOB_NAME"]
    def BUILD_STATUS = build.getEnvVars()["BUILD_STATUS"]
    def BUILD_URL = build.getEnvVars()["BUILD_URL"]

    def testResult = hudson.tasks.junit.TestResult

    def testResult2 = build.getAction(hudson.tasks.junit.TestResultAction.class)

%>

start test.groovy <br><br>
<b>TEST RESULT:</b> $testCount total, <b>$testPassed pass</b>, <b>$testFailed fail</b>, $testSkipped skip.<br>
Workspace : $workspace<br>
Project Name : $buildName $buildNumHash<br><br>

<!-- GENERAL INFO -->

<TABLE>
  <TR><TD align="right">
    <j:choose>
      <j:when test="${build.result=='SUCCESS'}">
        <IMG SRC="${rooturl}static/e59dfe28/images/32x32/blue.gif" />
      </j:when>
          <j:when test="${build.result=='FAILURE'}">
        <IMG SRC="${rooturl}static/e59dfe28/images/32x32/red.gif" />
      </j:when>
      <j:otherwise>
        <IMG SRC="${rooturl}static/e59dfe28/images/32x32/yellow.gif" />
      </j:otherwise>
    </j:choose>
  </TD><TD valign="center"><B style="font-size: 200%;">BUILD ${build.result}</B></TD></TR>
  <TR><TD>Build URL</TD><TD><A href="${rooturl}${build.url}">${rooturl}${build.url}</A></TD></TR>
  <TR><TD>Project:</TD><TD>${project.name}</TD></TR>
  <TR><TD>Date of build:</TD><TD>${it.timestampString}</TD></TR>
  <TR><TD>Build duration:</TD><TD>${build.durationString}</TD></TR>
  <TR><TD>Test duration:</TD><TD>${testDuration}</TD></TR>
</TABLE>
<BR/>

<!-- JUnit TEMPLATE  hudson.tasks.junit.TestResult   -->

<% def junitResultList = it.JUnitTestResult
try {
 def cucumberTestResultAction = it.getAction("org.jenkinsci.plugins.cucumber.jsontestsupport.CucumberTestResultAction")
 junitResultList.add(cucumberTestResultAction.getResult())
} catch(e) {
        //cucumberTestResultAction not exist in this build
}
// API: http://hudson-ci.org/javadoc/hudson/tasks/junit/PackageResult.html
%>

<!-- JUnit TEMPLATE: all tests PASS FAIL SKIP >
<% 
if (junitResultList.size() > 0) { %>
 <TABLE width="100%">
 <TR><TD class="bg1" colspan="2"><B>${junitResultList.first().displayName}</B></TD></TR>
 <% junitResultList.each{
  junitResult -> %>
     <% junitResult.getChildren().each { packageResult -> %>
        <TR><TD class="bg2" colspan="2"> <B>TEST SUITE: ${packageResult.getName()} Failed: ${packageResult.getFailCount()} test(s), Passed: ${packageResult.getPassCount()} test(s)</B>, Skipped: ${packageResult.getSkipCount()} test(s), Total: ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()} test(s)</TD></TR>
        <% packageResult.getChildren().each{ suite -> 
               suite.getChildren().each{ test ->
           def colour = "lightgreen"
           def highlight1=""
           def highlight2=""
           RESULT = test.getStatus() // FAILED or PASSED or SKIPPED
           if (RESULT == hudson.tasks.junit.CaseResult.Status.FAILED || RESULT == hudson.tasks.junit.CaseResult.Status.REGRESSION) {
               colour = "#ffcccc" 
               highlight1="<B>"
               highlight2="</B>"
           }
           if (RESULT == hudson.tasks.junit.CaseResult.Status.SKIPPED) { colour = "#ffffb3" }
         %>
          <TR bgcolor="${colour}"><TD class="test" colspan="2">${highlight1}<li>${RESULT}: ${test.getFullName()} </li>${highlight2}</TD></TR>
        <% } }
      }
 } %>
 </TABLE>
 <BR/>
<%
} %>

end of test.groovy

</body>
</html>

например. вывод (текст только без цветов/форматирование)

start test.groovy 

TEST RESULT: 18 total, 18 pass, 0 fail, 0 skip. 
Workspace : /var/lib/jenkins/jobs/jobname-1/workspace 
Project Name : jobname-1 #20

BUILD SUCCESS 

Build URL   http://jenkinsurl:port/job/jobname-1/20/
Project:    jobname-1 
Date of build:  Mon, 23 Jan 2017 09:29:00 +0000 
Build duration: 10 min 
Test duration:  267.12

Test Results 
TEST SUITE: suitename1 Failed: 0 test(s), Passed: 3 test(s), Skipped: 0 test(s), Total: 3 test(s) 
 * PASSED: suitename1.testclass.testname1
 * PASSED: suitename1.testclass.testname2
 * PASSED: suitename1.testclass.testname3
TEST SUITE: suitename2 Failed: 2 test(s), Passed: 1 test(s), Skipped: 0 test(s), Total: 3 test(s) 
 * PASSED: suitename2.testclass.testname1
 * FAILED: suitename2.testclass.testname2
 * REGRESSION: suitename2.testclass.testname3

end of test.groovy

Ответ 4

Мое решение в желе, основываясь на стандарте static-analysys.jelly script

  <!-- JUnit TEMPLATE -->
  <j:set var="junitResultList" value="${it.JUnitTestResult}" />
  <j:if test="${junitResultList.isEmpty()!=true}">
    <div class="content">
      <a href="${rooturl}${build.url}/testReport">
        <h1>JUnit Tests</h1>
      </a>
      <table class="border">
        <tr>
          <th class="border">Package</th>
          <th class="border">Failed</th>
          <th class="border">Failed (diff)</th>
          <th class="border">Passed</th>
          <th class="border">Passed (diff)</th>
          <th class="border">Skipped</th>
          <th class="border">Skipped (diff)</th>
          <th class="border">Total</th>
          <th class="border">Total (diff)</th>
        </tr>
        <j:forEach var="junitResult" items="${it.JUnitTestResult}">
          <j:forEach var="packageResult" items="${junitResult.getChildren()}">
            <tr>
              <td class="border">
                <tt>${packageResult.getName()}</tt>
              </td>
              <td class="border test_failed">${packageResult.getFailCount()}</td>
              <td class="border test_failed">${packageResult.getFailCount()-packageResult.previousResult.getFailCount()}</td>
              <td class="border test_passed">${packageResult.getPassCount()}</td>
              <td class="border test_passed">${packageResult.getPassCount()-packageResult.previousResult.getPassCount()}</td>
              <td class="border test_skipped">${packageResult.getSkipCount()}</td>
              <td class="border test_skipped">${packageResult.getSkipCount()-packageResult.previousResult.getSkipCount()}</td>
              <td class="border">
                <b>${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()}
                </b>
              </td>
              <td class="border">
                <b>${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()-packageResult.previousResult.getPassCount()-packageResult.previousResult.getFailCount()-packageResult.previousResult.getSkipCount()}
                </b>
              </td>
            </tr>
            <j:forEach var="failed_test"
              items="${packageResult.getFailedTests()}">
              <tr>
                <td class="test_failed" colspan="5">
                  <tt>${failed_test.getFullName()}</tt>
                </td>
              </tr>
            </j:forEach>
          </j:forEach>
        </j:forEach>
      </table>
      <br />
    </div>
  </j:if>