jmeter 接口测试 (分享build.xml+xsl html报告模版) 2020

这段时间按公司的要求整理jmeter 接口功能测试,最终参考网上资料,使用ant + jmeter 方式实现自动化结测试,其中测试用例使用csv配置,但是网上找到的html报告模版有两个,都不是让我台满意,最终了解了下xsl语言,将 两个报告模版合并了下,做成了如下效果:


image.png

点击每条用例后放的查看按钮可以展开操作,查看每条http的详细信息:


image.png

失败的效果:


image.png

项目结构:


image.png

UserCenterV1.0是我的项目接口部分,重点说下构成:

  • apache-ant-1.10.5 : ant 工具目录
  • apache-jmeter-5.2.1 : jmeter 工具目录
  • UserCenter_V1.0 : 中台接口V1.0 测试脚本和用例目录
    • 中台_合并版本_015_run.jmx : jmeter 脚本 (用户登录/用户管理/角色管理模块脚本)
    • UserCenter_V1.0/back-jmx : jmeter 脚本备份目录
    • UserCenter_V1.0/antjar : ant 工具依赖的第三方包 (主要是发送邮件用的)
    • UserCenter_V1.0/jmeterjar : jmeter 脚本测试依赖的第三方包 (备份使用,最终已经放到了jmeter的lib目录下)
    • UserCenter_V1.0/java : jmeter 脚本依赖的java工具脚本 (主要是自己写的工具类文件,如:密码校验,写用例结果到excel和响应结果检查等)
    • UserCenter_V1.0/report : 最终生成的报告数据,包含两部分:分别是每个用例用对应的excel执行结果和html报告结果。
    • UserCenter_V1.0/templets : html测试用例模版
    • UserCenter_V1.0/images : 第三方资源 (目前暂时放的测试中需要的用户头像)
    • UserCenter_V1.0/build.xml: ant 自动化运行的配置参数
    • UserCenter_V1.0/userlogin_006 :用户登录模块测试用例(数据部分)
    • UserCenter_V1.0/usermanager_002 :用户管理模块测试用例(数据部分)
    • UserCenter_V1.0/rolemanager_001 :角色管理模块测试用例(数据部分)

jmx脚本部分:
测试用例使用的csv:(每个模块单独一个测试用例,单独使用一个线程组进行读取csv)


image.png

测试用例部分csv:


image.png

我的jmeter的xsl html 报告模版
jmeter-result-sleeli.xsl

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <!--
       Licensed to the Apache Software Foundation (ASF) under one or more
       contributor license agreements.  See the NOTICE file distributed with
       this work for additional information regarding copyright ownership.
       The ASF licenses this file to You under the Apache License, Version 2.0
       (the "License"); you may not use this file except in compliance with
       the License.  You may obtain a copy of the License at

           http://www.apache.org/licenses/LICENSE-2.0

       Unless required by applicable law or agreed to in writing, software
       distributed under the License is distributed on an "AS IS" BASIS,
       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       See the License for the specific language governing permissions and
       limitations under the License.
    -->

    <!--
        Stylesheet for processing 2.1 output format test result files
        To uses this directly in a browser, add the following to the JTL file as line 2:
        <?xml-stylesheet type="text/xsl" href="../extras/jmeter-results-detail-report_21.xsl"?>
        and you can then view the JTL in a browser
    -->

    <xsl:output method="html" indent="yes" encoding="UTF-8" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" />

    <!-- Defined parameters (overrideable) -->
    <xsl:param    name="showData" select="'n'"/>
    <xsl:param    name="titleReport" select="'接口测试报告'"/>
    <xsl:param    name="dateReport" select="'日期无法获取'"/>

    <xsl:template match="testResults">
        <html>
            <head>
                <title><xsl:value-of select="$titleReport" /></title>
                <style type="text/css">
                    body {
                    font:normal 68% verdana,arial,helvetica;
                    color:#000000;
                    }
                    table tr td, table tr th {
                    font-size: 68%;
                    }
                    table.details tr th{
                    color: #ffffff;
                    font-weight: bold;
                    text-align:center;
                    background:#2674a6;
                    white-space: nowrap;
                    }
                    table.details tr td{
                    background:#eeeee0;
                    white-space: nowrap;
                    width: 10em;
                    }

                    table.detail-panel tr td{
                    background:#eeeee0;
                    white-space: nowrap;
                    width: auto;
                    }

                    h1 {
                    margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
                    }
                    h2 {
                    margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica
                    }
                    h3 {
                    margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica
                    }
                    .Failure {
                    font-weight:bold; color:red;
                    }
                    .Success{
                    font-weight:bold; color:#07d422;
                    }

                    img
                    {
                    border-width: 0px;
                    }

                    .expand_link
                    {
                    position=absolute;
                    right: 0px;
                    width: 27px;
                    top: 1px;
                    height: 27px;
                    }

                    .page_details
                    {
                    display: none;
                    }

                    .page_details_expanded
                    {
                    display: block;
                    display/* hide this definition from  IE5/6 */: table-row;
                    }


                    #detail-panel .group { font-size: 12px; font-weight: bold; line-height: 16px; padding: 0 0 0 18px; counter-reset: assertion; background-repeat: repeat-x; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAQCAYAAADXnxW3AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDEBUkDq8pxjkAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAADdJREFUCNdVxrERwDAMAzGK0v47eS6Z927SpMFBAAbkvSvnRk5+7K5cVfLMyN39bWakJAjA5xw9R94jN3tVhVEAAAAASUVORK5CYII=) }
                    #detail-panel .zebra { background-repeat: repeat; padding: 0 0 0 0px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAmCAYAAAAFvPEHAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDEBYWFlNztEcAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAABdJREFUCNdjYKAtePv5338mBgYGBpoQAGy1BAJlb/y6AAAAAElFTkSuQmCC) }
                    #detail-panel .data { line-height: 19px; white-space: nowrap }
                    #detail-panel pre.data { white-space: pre-wrap; word-wrap: break-word; width:100%  }
                    #detail-panel tbody.failure { color: red }
                    #detail-panel td.key { font-weight: bold; min-width: 108px }
                    #detail-panel td.delimiter { min-width: 18px }
                    #detail-panel td.assertion:before { counter-increment: assertion; content: counter(assertion) ". " }
                    #detail-panel td.assertion { color: black }
                    #detail-panel .trail { border-top: 1px solid #b4b4b4 }

                </style>
                <script language="JavaScript"><![CDATA[
                           function expand(details_id)
               {

                  document.getElementById(details_id).className = "page_details_expanded";
               }

               function collapse(details_id)
               {

                  document.getElementById(details_id).className = "page_details";
               }

               function change(details_id)
               {
                  if(document.getElementById(details_id+"_image").src.match("expand"))
                  {
                     document.getElementById(details_id+"_image").src = "collapse.png";
                     expand(details_id);
                  }
                  else
                  {
                     document.getElementById(details_id+"_image").src = "expand.png";
                     collapse(details_id);
                  }
                           }
            ]]></script>
            </head>
            <body>

                <xsl:call-template name="pageHeader" />

                <xsl:call-template name="summary" />
                <hr size="1" width="95%" align="center" />

                <xsl:call-template name="pagelist" />
                <hr size="1" width="95%" align="center" />


                <!-- <xsl:call-template name="detail" /> -->

            </body>
        </html>
    </xsl:template>

    <xsl:template name="pageHeader">
        <h1><xsl:value-of select="$titleReport" /></h1>
        <table width="100%">
            <tr>
                <td align="left">报告生成日期: <xsl:value-of select="$dateReport" /></td>
                <td align="right">Designed for use with <a href="http://jmeter.apache.org/">JMeter</a> and <a href="http://ant.apache.org">Ant</a>.</td>
            </tr>
        </table>
        <hr size="1" />
    </xsl:template>

    <xsl:template name="summary">
        <h2>   用例执行统计: </h2>
        <table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
            <tr valign="top">
                <th>用例总数</th>
                <th>成功用例数</th>
                <th>失败用例数</th>
                <th>用例通过率</th>
                <th>平均时间</th>
                <th>最小时间</th>
                <th>最大时间</th>
            </tr>
            <tr valign="top">
                <xsl:variable name="allCount" select="count(/testResults/httpSample)" />
                <xsl:variable name="allFailureCount" select="count(/testResults/httpSample[attribute::s='false'])" />
                <xsl:variable name="allSuccessCount" select="count(/testResults/httpSample[attribute::s='true'])" />
                <xsl:variable name="allSuccessPercent" select="$allSuccessCount div $allCount" />
                <xsl:variable name="allTotalTime" select="sum(/testResults/httpSample/@t)" />
                <xsl:variable name="allAverageTime" select="$allTotalTime div $allCount" />
                <xsl:variable name="allMinTime">
                    <xsl:call-template name="min">
                        <xsl:with-param name="nodes" select="/testResults/httpSample/@t" />
                    </xsl:call-template>
                </xsl:variable>
                <xsl:variable name="allMaxTime">
                    <xsl:call-template name="max">
                        <xsl:with-param name="nodes" select="/testResults/httpSample/@t" />
                    </xsl:call-template>
                </xsl:variable>

                <td align="center">
                    <xsl:value-of select="$allCount" />
                </td>
                <td align="center">
                    <xsl:value-of select="$allSuccessCount" />
                </td>
                <td align="center">
                    <xsl:attribute name="class">
                        <xsl:choose>
                            <xsl:when test="$allFailureCount &gt; 0">Failure</xsl:when>
                        </xsl:choose>
                    </xsl:attribute>
                    <xsl:value-of select="$allFailureCount" />
                </td>
                <td align="center">
                    <xsl:call-template name="display-percent">
                        <xsl:with-param name="value" select="$allSuccessPercent" />
                    </xsl:call-template>
                </td>
                <td align="center">
                    <xsl:call-template name="display-time">
                        <xsl:with-param name="value" select="$allAverageTime" />
                    </xsl:call-template>
                </td>
                <td align="center">
                    <xsl:call-template name="display-time">
                        <xsl:with-param name="value" select="$allMinTime" />
                    </xsl:call-template>
                </td>
                <td align="center">
                    <xsl:call-template name="display-time">
                        <xsl:with-param name="value" select="$allMaxTime" />
                    </xsl:call-template>
                </td>
            </tr>
        </table>
    </xsl:template>

    <xsl:template name="pagelist">
        <h2>   用例执行列表: </h2>
        <table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
            <tr valign="top">
                <th>模块名称</th>
                <th>接口名称</th>
                <th>用例ID</th>
                <th>用例类型</th>
                <th>前置条件</th>
                <th>用例名称</th>
                <!--
                <th>成功次数</th>
                <th>失败次数</th>
                <th>成功率</th>

                <th>平均时间</th>
                <th>最小时间</th>
                <th>最大时间</th>
                -->
                <th>花费时间</th>
                <th>执行结果</th>
                <th>查看详情</th>

            </tr>
            <xsl:for-each select="/testResults/httpSample[not(@lb = preceding::*/@lb)]">
                <!-- 用例名称需要截取处理   执行用例-用户登录-用户登录模块-case_login_001-场景_正常业务-未登录-强制登录_成功登录  -->
                <xsl:variable name="label" select="@lb" />
                <xsl:variable name="separator" select="'-'" />

                <xsl:variable name="first" select="substring-before($label, $separator)" />
                <xsl:variable name="first-after" select="substring-after($label, $separator)" />

                <xsl:variable name="interfaceName" select="substring-before($first-after, $separator)" />
                <xsl:variable name="second-after" select="substring-after($first-after, $separator)" />

                <xsl:variable name="modelName" select="substring-before($second-after, $separator)" />
                <xsl:variable name="third-after" select="substring-after($second-after, $separator)" />

                <xsl:variable name="caseId" select="substring-before($third-after, $separator)" />
                <xsl:variable name="fourth-after" select="substring-after($third-after, $separator)" />

                <xsl:variable name="caseType" select="substring-before($fourth-after, $separator)" />
                <xsl:variable name="fifth-after" select="substring-after($fourth-after, $separator)" />

                <xsl:variable name="caseIf" select="substring-before($fifth-after, $separator)" />
                <xsl:variable name="caseName" select="substring-after($fifth-after, $separator)" />

                <!-- 统计数据列-->
                <xsl:variable name="count" select="count(../*[@lb = current()/@lb])" />
                <xsl:variable name="failureCount" select="count(../*[@lb = current()/@lb][attribute::s='false'])" />
                <xsl:variable name="successCount" select="count(../*[@lb = current()/@lb][attribute::s='true'])" />
                <xsl:variable name="successPercent" select="$successCount div $count" />
                <xsl:variable name="totalTime" select="sum(../*[@lb = current()/@lb]/@t)" />
                <xsl:variable name="averageTime" select="$totalTime div $count" />
                <xsl:variable name="minTime">
                    <xsl:call-template name="min">
                        <xsl:with-param name="nodes" select="../*[@lb = current()/@lb]/@t" />
                    </xsl:call-template>
                </xsl:variable>
                <xsl:variable name="maxTime">
                    <xsl:call-template name="max">
                        <xsl:with-param name="nodes" select="../*[@lb = current()/@lb]/@t" />
                    </xsl:call-template>
                </xsl:variable>
                <tr valign="top">
                    <!--
                    <xsl:attribute name="class">
                        <xsl:choose>
                            <xsl:when test="$failureCount &gt; 0">Failure</xsl:when>
                        </xsl:choose>
                    </xsl:attribute>
                    -->
                    <td align="center" font-weight="bold" ><xsl:value-of select="$modelName" /> </td>
                    <td align="center" ><xsl:value-of select="$interfaceName" /></td>
                    <td align="center" ><xsl:value-of select="$caseId" /></td>
                    <td align="center" ><xsl:value-of select="$caseType" /></td>
                    <td align="center" ><xsl:value-of select="$caseIf" /></td>
                    <td>
                        <xsl:if test="$failureCount > 0">
                            <a>
                                <!-- <xsl:attribute name="href">#<xsl:value-of select="$label" /></xsl:attribute> -->

                                <xsl:value-of select="$caseName" />
                            </a>
                        </xsl:if>
                        <xsl:if test="0 >= $failureCount">
                            <xsl:value-of select="$caseName" />
                        </xsl:if>
                    </td>
                    <!--
                    <td align="center">
                        <xsl:value-of select="$successCount" />
                    </td>
                    <td align="center">
                        <xsl:value-of select="$failureCount" />
                    </td>
                    <td align="right">
                        <xsl:call-template name="display-percent">
                            <xsl:with-param name="value" select="$successPercent" />
                        </xsl:call-template>
                    </td>
                    <td align="right">
                        <xsl:call-template name="display-time">
                            <xsl:with-param name="value" select="$averageTime" />
                        </xsl:call-template>
                    </td>
                    <td align="right">
                        <xsl:call-template name="display-time">
                            <xsl:with-param name="value" select="$minTime" />
                        </xsl:call-template>
                    </td>
                    <td align="right">
                        <xsl:call-template name="display-time">
                            <xsl:with-param name="value" select="$maxTime" />
                        </xsl:call-template>
                    </td>
                    -->
                    <td align="right">
                        <xsl:call-template name="display-time">
                            <xsl:with-param name="value" select="$totalTime" />
                        </xsl:call-template>
                    </td>
                    <td align="center">
                        <xsl:if test="$failureCount > 0">
                            <xsl:attribute name="class">Failure</xsl:attribute>
                            <xsl:value-of select="'不通过'" />
                        </xsl:if>
                        <xsl:if test="0 = $failureCount">
                            <xsl:attribute name="class">Success</xsl:attribute>
                            <xsl:value-of select="'通过'" />
                        </xsl:if>
                    </td>
                    <td align="center">
                        <a href="">
                            <xsl:attribute name="href"><xsl:text/>javascript:change('page_details_<xsl:value-of select="position()" />')</xsl:attribute>
                            <img src="expand.png" alt="展开/折叠"><xsl:attribute name="id"><xsl:text/>page_details_<xsl:value-of select="position()" />_image</xsl:attribute></img>
                        </a>
                    </td>
                </tr>

                <tr class="page_details">
                    <xsl:attribute name="id"><xsl:text/>page_details_<xsl:value-of select="position()" /></xsl:attribute>
                    <td colspan="9">
                        <table id="detail-panel" bordercolor="#000000" bgcolor="#2674A6" border="0"  cellpadding="1" cellspacing="1"  >

                            <tr> <td> <b> 请求和响应详情:  "<xsl:value-of select="$label" />"</b>  </td></tr>

                            <tr> <td> <div class="group">Sampler:</div>  </td></tr>
                            <tr> <td> <div class="zebra">
                                <table>
                                    <tr><td class="data key">Thread Name</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@tn"/></td></tr>
                                    <tr><td class="data key">Timestamp</td><td class="data delimiter">:</td><td class="data"><span class="patch_timestamp"><xsl:value-of select="@ts"/></span></td></tr>
                                    <tr><td class="data key">Time</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@t"/> ms</td></tr>
                                    <tr><td class="data key">Latency</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@lt"/> ms</td></tr>
                                    <tr><td class="data key">Bytes</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@by"/></td></tr>
                                    <tr><td class="data key">Sample Count</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@sc"/></td></tr>
                                    <tr><td class="data key">Error Count</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@ec"/></td></tr>
                                    <tr><td class="data key">Response Code</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@rc"/></td></tr>
                                    <tr><td class="data key">Response Message</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@rm"/></td></tr>
                                </table>
                            </div>  </td></tr>
                            <tr> <td> <div class="trail"></div>  </td></tr>

                            <xsl:if test="count(assertionResult) &gt; 0">
                                <tr> <td> <div class="group">断言信息:</div>  </td></tr>
                                <tr> <td> <div class="zebra">
                                    <table>
                                        <xsl:for-each select="assertionResult">
                                            <tbody>
                                                <xsl:attribute name="class">
                                                    <xsl:choose>
                                                        <xsl:when test="failure = 'true'">failure</xsl:when>
                                                        <xsl:when test="error = 'true'">failure</xsl:when>
                                                    </xsl:choose>
                                                </xsl:attribute>
                                                <tr><td class="data assertion" colspan="3"><xsl:value-of select="name"/></td></tr>
                                                <tr><td class="data key">Failure</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="failure"/></td></tr>
                                                <tr><td class="data key">Error</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="error"/></td></tr>
                                                <tr><td class="data key">Failure Message</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="failureMessage"/></td></tr>
                                            </tbody>
                                        </xsl:for-each>
                                    </table>
                                </div>  </td></tr>
                                <tr> <td> <div class="trail"></div>  </td></tr>
                            </xsl:if>

                            <tr> <td> <div class="group">请求信息:</div>  </td></tr>
                            <tr> <td> <div class="zebra">
                                <table>
                                    <tr><td class="data key">Url</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="java.net.URL"/></pre></td></tr>
                                    <tr><td class="data key">Method</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="method"/></pre></td></tr>
                                    <tr><td class="data key">Query String</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="queryString"/></pre></td></tr>
                                    <tr><td class="data key">Cookies</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="cookies"/></pre></td></tr>
                                    <tr><td class="data key">Request Headers</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="requestHeader"/></pre></td></tr>
                                </table>
                            </div>  </td></tr>
                            <tr> <td> <div class="trail"></div>  </td></tr>


                            <tr> <td> <div class="group">响应信息:</div>  </td></tr>
                            <tr> <td> <div class="zebra">
                                <table>
                                    <tr><td class="data key">Response Headers</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="responseHeader"/></pre></td></tr>
                                    <tr><td class="data key">Response Data</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="responseData"/></pre></td></tr>
                                    <tr><td class="data key">Response File</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="responseFile"/></pre></td></tr>
                                </table>
                            </div>   </td></tr>
                            <tr> <td> <div class="trail"></div>   </td></tr>



                        </table>
                    </td>
                </tr>

            </xsl:for-each>
        </table>
    </xsl:template>

    <xsl:template name="detail">
        <xsl:variable name="allFailureCount" select="count(/testResults/httpSample[attribute::s='false'])" />

        <xsl:if test="$allFailureCount > 0">
            <h2>  执行用例失败详情: </h2>

            <xsl:for-each select="/testResults/*[not(@lb = preceding::*/@lb)]">

                <xsl:variable name="failureCount" select="count(../*[@lb = current()/@lb][attribute::s='false'])" />

                <xsl:if test="$failureCount > 0">
                    <h3><xsl:value-of select="@lb" /><a><xsl:attribute name="name"><xsl:value-of select="@lb" /></xsl:attribute></a></h3>

                    <table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
                        <tr valign="top">
                            <th>Response</th>
                            <th>Failure Message</th>
                            <xsl:if test="$showData = 'y'">
                                <th>Response Data</th>
                            </xsl:if>
                        </tr>

                        <xsl:for-each select="/testResults/*[@lb = current()/@lb][attribute::s='false']">
                            <tr>
                                <td><xsl:value-of select="@rc | @rs" /> - <xsl:value-of select="@rm" /></td>
                                <td><xsl:value-of select="assertionResult/failureMessage" /></td>
                                <xsl:if test="$showData = 'y'">
                                    <td><xsl:value-of select="./binary" /></td>
                                </xsl:if>
                            </tr>
                        </xsl:for-each>

                    </table>
                </xsl:if>

            </xsl:for-each>
        </xsl:if>
    </xsl:template>

    <xsl:template name="min">
        <xsl:param name="nodes" select="/.." />
        <xsl:choose>
            <xsl:when test="not($nodes)">NaN</xsl:when>
            <xsl:otherwise>
                <xsl:for-each select="$nodes">
                    <xsl:sort data-type="number" />
                    <xsl:if test="position() = 1">
                        <xsl:value-of select="number(.)" />
                    </xsl:if>
                </xsl:for-each>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template name="max">
        <xsl:param name="nodes" select="/.." />
        <xsl:choose>
            <xsl:when test="not($nodes)">NaN</xsl:when>
            <xsl:otherwise>
                <xsl:for-each select="$nodes">
                    <xsl:sort data-type="number" order="descending" />
                    <xsl:if test="position() = 1">
                        <xsl:value-of select="number(.)" />
                    </xsl:if>
                </xsl:for-each>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template name="display-percent">
        <xsl:param name="value" />
        <xsl:value-of select="format-number($value,'0.00%')" />
    </xsl:template>

    <xsl:template name="display-time">
        <xsl:param name="value" />
        <xsl:value-of select="format-number($value,'0 ms')" />
    </xsl:template>

</xsl:stylesheet>

另外附上ant + jmeter 实现的build.xml 的自动执行和发送邮件功能
build.xml

<?xml version="1.0" encoding="UTF-8"?>

<project name="UserCenter_V1.0" default="run" basedir="/Users/sleeli/Desktop/工作文档-2020/jmeter_work">


    <!-- 需要改成自己本地的 Jmeter 目录-->  
    <property name="jmeter.home" value="${basedir}/apache-jmeter-5.2.1" />
    <property name="project.report.title" value="接口测试"/>
    
    <!-- 需要改成自己本地的 项目的 目录-->  
    <property name="project.home" value="${basedir}/UserCenter_V1.0" />
       
    <tstamp>
        <format property="time" pattern="yyyyMMdd_hhmm" />
    </tstamp>
    <tstamp>
        <format property="date_time" pattern="yyyy/MM/dd hh:mm:ss" />
    </tstamp>
    
    <!-- 配置邮件信息 发送人信息和账号密码 以及发送到-->  
    <property name="mail_host" value="smtp.exmail.qq.com"/>
    <property name="mail_port" value="465"/>
    <property name="username" value="sender@qq.com"/>
     <!-- 如果使用QQ需要先在QQ邮箱设置里开启smtp服务,会获得一个授权码,此处填写那个授权码 --> 
    <property name="password" value="******"/>
    <property name="mail_from" value="sender@qq.com"/>
    <property name="mail_to" value="accpet1@qq.com,accpet2@qq.com"/>
    <property name="mail_cc" value="cc1@qq.com"/>
    <property name="mailsubject" value="这是一封测试报告邮件_${time}"/>
    <property name="message" value="
           各位好:&lt;br /&gt;&lt;br /&gt;
             中台项目接口在${date_time}时间执行测试成功,执行结果详情请见附件,请注意查收!&lt;br /&gt;&lt;br /&gt;
                 &lt;br /&gt;&lt;br /&gt;
        "/>
        
     <!-- jmeter使用的脚本--> 
    <property name="project.jmx.dirs" value="${project.home}" />
    <!-- 声明要运行的脚本"*_run.jmx"指包含此目录下的所有jmeter脚本-->
    <property name="project.jmx.dirs.regName" value="*_run.jmx" />
 
    
    <!-- jmeter生成报告使用的模板xls--> 
    <property name="project.report.templets.dirs" value="${project.home}/templets" />
    
    <property name="project.report.templet.detail" value="${project.report.templets.dirs}/jmeter-result-sleeli.xls" />
    
    
    <!-- jmeter生成jtl格式的结果报告的路径--> 
    <property name="jmeter.result.jtl.dir" value="${project.home}/report" />
    <!-- jmeter生成html格式的结果报告的路径-->
    <property name="jmeter.result.html.dir" value="${project.home}/report" />
    
    <!-- 生成的报告的前缀 -->  
    <property name="ReportName" value="TestReport_UserCenter_V1.0" />
    
    <property name="jmeter.result.jtlName" value="${jmeter.result.jtl.dir}/${ReportName}_${time}.jtl" />
    <property name="jmeter.result.detail.htmlName" value="${jmeter.result.html.dir}/${ReportName}_detail_${time}.html" />


    <!-- 运行target 调用顺序 -->
    <target name="run">
            <antcall target="delete" />
        <antcall target="test" />
        <antcall target="report" />
        <antcall target="mail" />
    </target>
    
    <!--删除所有符合规范的文件报告文件 -->
      <target name="delete">
        <echo message="delete dir=${jmeter.result.html.dir}/*  files!!!! "/>
            <delete >
                <fileset dir="${jmeter.result.html.dir}" includes="*"/>
            </delete>
        </target>
    
    <target name="test">
        <taskdef name="jmeter" classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask" />
        <jmeter jmeterhome="${jmeter.home}" resultlog="${jmeter.result.jtlName}">
            <!-- 声明要运行的脚本。"*_run.jmx"指包含此目录下的所有jmeter脚本-->
            <testplans dir="${project.jmx.dirs}" includes="${project.jmx.dirs.regName}" />
            <property name="jmeter.save.saveservice.output_format" value="xml"/>
        </jmeter>
    </target>
    
     <path id="xslt.classpath">
        <fileset dir="${jmeter.home}/lib" includes="xalan*.jar"/>
        <fileset dir="${jmeter.home}/lib" includes="serializer*.jar"/>
     </path>
        
    <target name="report">
        <tstamp> <format property="report.datestamp" pattern="yyyy/MM/dd HH:mm" /></tstamp>    
            
    <xslt 
              classpathref="xslt.classpath"
              force="true"
              in="${jmeter.result.jtlName}"
              out="${jmeter.result.detail.htmlName}"
              style="${project.report.templet.detail}">
              <param name="dateReport" expression="${report.datestamp}"/>
            </xslt>
    
                <!-- 因为上面生成报告的时候,不会将相关的图片也一起拷贝至目标目录,所以,需要手动拷贝 --> 
        <copy todir="${jmeter.result.html.dir}">
            <fileset dir="${jmeter.home}/extras">
                <include name="collapse.png" />
                <include name="expand.png" />
            </fileset>
        </copy>
    </target>    
    
    <path id="lib_classpath">
         <fileset dir="${basedir}/">
             <include name="mail*.jar" />
             <include name="activation*.jar" />
             <include name="commons-email*.jar" />
             <include name="ant-contrib*.jar" />
         </fileset>
  </path>
  <target name="mail">
          <echo>发送测试报告</echo>
          <echo>mail_from=${mail_from}</echo>
          <echo>mail_to=${mail_to}</echo>
          <echo>mail_cc=${mail_cc}</echo>
            <mail mailhost="${mail_host}" 
                  ssl="true"
                  user="${username}"
                  password="${password}"
                  mailport="${mail_port}"
                  subject="${mailsubject}"
                  messagemimetype="text/html"
                  tolist="${mail_to}"
                  cclist="${mail_cc}"  >
                     <from address="${mail_from}" />
           <fileset dir="${jmeter.result.html.dir}">
              <include name="*.html" />
              <include name="*.xls" />
              <include name="*.png" />
           </fileset>
           <message> 
            ${message}
           </message>
       </mail>
     </target> 

</project>

报告效果:(报告我弄了两种,一种是html报告)
一种是使用xsl模版生成html报告,适合汇报给领导和开发人员查看执行效果,一幕了然
html效果图:


image.png

点击每条用例后放的查看按钮可以展开操作,查看每条http的详细信息:


image.png

失败的效果:
image.png

另外一种是我在csv测试用例的基础上,将csv测试用例每次执行后复制一份后面的测试结果填写上的:


image.png

说明:红色箭头的地方是,表示由于请求参数中包含动态的变量部分,请求参数在请求前需要预处理,故需要将请求重新加一列记录下实际的请求信息,方便后面有问题定位。

另外最终,只需要在我的工程目录下,输入ant 后,自动回将结果打包发送到我的邮箱了 ,nice~


image.png

大概就这么多,后面优化在发出来吧~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容