如何编写Jenkins电子邮件ext模板以显示标准测试报告等测试结果

如何编写Jenkins电子邮件ext模板以显示标准测试报告等测试结果,jenkins,hudson,jelly,email-ext,Jenkins,Hudson,Jelly,Email Ext,我已经调整了标准的jelly模板以在表中显示当前的测试结果,但是我真的希望能够显示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

我已经调整了标准的jelly模板以在表中显示当前的测试结果,但是我真的希望能够显示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

为EmailExt插件编写Groovy模板,而不是Jelly模板。在Groovy模板中,您将可以访问用于构建的对象。然后,您可以调用它来获取构建的属性,然后可以查询所需的所有内容


这里是一个链接。Ext电子邮件插件的Groovy模板示例可以在
$JENKINS\u HOME/plugins/Email Ext/WEB-INF/classes/hudson/plugins/emailext/templates/Groovy html.template
中找到。有关Groovy模板/脚本使用的更多信息,请参阅。

如果您在如何通过内部API访问它方面遇到困难(很难知道,而且总是存在限制),那么还有另一种更灵活的方法

使用文件令牌代替groovy模板

  • 使用脚本访问您的测试数据,对于您的情况,就像在工作区下生成自己的html文件一样,如
    email.html
  • 在电子邮件ext配置的
    默认内容
    表单中,使用文件令牌直接发送电子邮件
    ${FILE,path=“email.html”}
  • 在上面的步骤1中,您还可以使用更灵活的方式为您自己的模板,我使用python脚本和简单的字符串模板


    它非常适合我。

    我在Jelly中基于默认的static-analysys.Jelly脚本的解决方案

      <!-- 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>
    
    
    包裹
    失败
    失败(差异)
    通过
    通过(差异)
    跳过
    跳过(差异)
    全部的
    总计(差异)
    ${packageResult.getName()}
    ${packageResult.getFailCount()}
    ${packageResult.getFailCount()-packageResult.previousResult.getFailCount()}
    ${packageResult.getPassCount()}
    ${packageResult.getPassCount()-packageResult.previousResult.getPassCount()}
    ${packageResult.getSkipCount()}
    ${packageResult.getSkipCount()-packageResult.previousResult.getSkipCount()}
    ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()}
    ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()-packageResult.previousResult.getPassCount()-packageResult.previousResult.getFailCount()-packageResult.previousResult.getSkipCount()}
    ${测试失败。getFullName()}
    
    要扩展此答案: 为EmailExt插件编写Groovy模板,而不是Jelly模板。 在可编辑的电子邮件通知内容中

    • 将内容类型设置为“HTML”或“HTML和纯文本”
    • 并包括如下所示的groovy脚本:

      ${SCRIPT,template=“test.groovy”}

    • 将groovy脚本放在电子邮件模板中。 /var/lib/jenkins/email模板。请参见下面的test.groovy

    在下面的示例中,每个测试都是通过获取以下对象来迭代的:“junitResult.getChildren()”。如果希望只迭代失败的测试,那么可以使用junitResult.getFailedTests()。请参见hudson.tasks.junit.TestResult API:另请参见


    诱惑朱尼特


    @Jon,这个答案有用吗?我已经使用build.testResultAction.failedTests成功地排除了失败的测试,但我不确定如何访问所有测试,例如访问PackageResult的测试依赖于getTestResultAction返回的类型-AggregatedTestResultAction和TestResultAction需要不同的处理。下面是一个例子。现在使用Jenkins管道“更容易”了,您可以在Jenkins文件中的
    @NonCPS
    注释方法中编写电子邮件模板,并使用
    def testResult=currentBuild.rawBuild.getAction(hudson.tasks.junit.TestResultAction.class)
    访问测试结果。您是否愿意共享步骤1中描述的脚本?如果使用HTML格式,则需要使用
    ${SCRIPT,template=“groovy html.template”}
    而不是
    ${FILE}
    。请详细说明一下这一点。我想我需要做类似的事情。我想在电子邮件中显示来自git的完整git commit消息。但它只显示第一行。我想我需要编写一些脚本。@leway你来了,我们需要创建模板并将其放入jenkins文件夹或其他什么东西吗?请提供详细信息什么指示?
    Collection<ClassResult> getChildren()
    List<CaseResult>    getFailedTests()
    
    <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