首页 > 技术文章 > Jmeter +Jenkins +Ant 集成发送邮件报告

crstyl 2021-03-05 11:03 原文

[TOC]

 

一、什么是接口测试?

 

接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关系等。

 

接口测试适用于为其他系统提供服务的底层框架系统和中心服务系统,主要测试这些系统对外部提供的接口,验证其正确性和稳定性。接口测试同样适用于一个上层系统中的服务层接口,越往上层,其测试的难度越大。

 

接口测试实施在多系统多平台的构架下,有着极为高效的成本收益比,接口测试天生为高复杂性的平台带来高效的缺陷监测和质量监督能力。平台越复杂,系统越庞大,接口测试的效果越明显。

 

基于接口测试的重要性,以及它比较容易自动化的特性,通过持续集成的接口监控能够及时的发现项目中存在的问题,这对持续运营的项目来说,非常重要。

 

二、接口测试的流程

 

1、 项目启动后,测试人员要尽早找到开发人员拿到接口测试文档

 

2、 获取接口测试文档后,就可以进行接口用例的编写和调试

 

3、 接口用例编写调试完成后,部署到持续集成的测试环境中,

 

4、 设定脚本运行频率,告警方式等基本参数,进行接口的日常监控

 

5、 每日进行接口脚本的维护更新,接口异常的处理

 

三、jenkins + ant + jmeter 集成测试报告发送邮件

 

环境准备

 

  • 安装Jdk
    JDK是Java语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。
    1. 鼠标右击计算机(此电脑)->属性->高级系统设置->高级->环境变量
    2. 在系统变量中,点击新建,新建JAVA_HOME变量,变量的值:JDK的安装目录
      image
    3. 在系统变量中找到Path变量,双击打开,新增两个变量%JAVA_HOME%\bin%JAVA_HOME%\jre\bin,点击确定

 

image

    1. 在系统变量中新建CLASSPATH变量,变量值:.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar(注意前面的.),点击确定,保存退出。

 

image

    1. 检查是否配置成功,win+R输入cmd,然后回车,在黑乎乎的窗口输入java -version,能够看到你安装的jdk版本信息,即环境配置成功。

 

image

  • 安装Ant
    ant 是Apache软件基金会JAKARTA目录中的一个子项目,它有以下的优点:
    1、跨平台性:Ant是纯Java语言编写的,所以具有很好的跨平台性。
    2、操作简单:Ant是由一个内置任务和可选任务组成的,用ant任务就像是在dos中写命令行一样。Ant运行时需要一个XML文件(构建文件)。 Ant通过调用target树,就可以执行各种task。每个task实现了特定接口对象。
    3、维护简单、可读性好、集成简单:由于Ant构建文件 时XML格式的文件,所以很容易维护和书写,而且结构很清晰。Ant可以集成到开发环境中。由于Ant的跨平台性和操作简单的特点,它很容易集成到一些开 发环境中去。
    以下是解压后的目录布局。
apache-ant-1.10.8
 +--- README, LICENSE, fetch.xml, 其他文本文件. //基本信息
 +--- bin // 包含安装程序脚本
 |
 +--- lib // 包含Ant JARs plus必要的依赖项
 |
 +--- manual // Ant文档 (必读 ;-)
 |
 +--- etc // 包含xsl工具:
          // - 可以从xml输出的各种任务中创建一个增强型的报告。
          // - 迁移你的构建文件,并摆脱 "已废弃 "的警告
          // - ... 更多 ;-)
    1. 点击http://ant.apache.org/bindownload.cgi进入ant官网,下载对应的安装包。
      image
    2. 将下载的.zip压缩包解压到对应文件夹
    3. 配置环境变量
ANT_HOME  H:\Ant\apache-ant-1.10.2
path       H:\Ant\apache-ant-1.10.2\bin
classpath   H:\Ant\apache-ant-1.10.2\lib
    1. 验证是否安装成功
      依次选择:win + R –>cmd,输入如下命令:ant  ,出现如下图,则表示安装成功
      image
  • 安装jenkins
    jenkins有三种安装方式
    第一种:快速安装
    选择windows系统的版本
    image
    解压成功后双击jenkins.msi程序
    image
    安装成功后会显示如下要你填写密码的验证页面,按照它的提示信息到对应的目录底下找文件initialAdminPassword,然后将密码拷贝出来   localhost:8080
    image
    第二种:快速安装
    使用命令 java -jar jenkins.war
    这是依赖于 java环境和 jenkins.war进行搭建
    这里不多说,因为后面的安装顺序都是和上述一致
    第三种方法:
    是直接将jenkins.war包安装在tomcat的webapps目录下,然后启动tomcatcat就可以了,当然Tomcat也有两种启动方式。但原理都是一样的。只是看谁比较方便,兼容性比较强而已。关键还是看系统 st
    startup.sh
    总结:三种安装方式都使用与Windows系统,第二种和第三种可以使用在linux系统,但是为求不出错,第二种才是最方便的。如果直接将jenkins.war包放到Tomcat的webapps下,那你公司的项目也放到这里,那就好玩了。
    此处, 我们选择第一种方式进行安装
  • 配置jmeter变量
    1. 官网下载
      image
    2. 解压任意目录即可
    3. 配置环境变量
      点击“新建”,建立一个变量:JMETER_HOME,值为你解压的jmeter安装路径。我的安装路径是在C盘,这个路径根据自己实际安装路径进行填写。然后点击确定保存即可
      image
      配置classpath变量 ;
%JMETER_HOME%\lib\ext\ApacheJMeter_core.jar;%JMETER_HOME%\lib\jorphan.jar;%JMETER_HOME%\lib/logkit-2.0.jar
    1. image
      在用系统变量path后面加上%JMETER_HOME%\bin
      image
      最后在cmd输入jmeter 直接打开 如图

 

配置jenkins

 

环境变量配置

 

  1. 全局系统环境变量配置JDK
    image
  2. 全局系统环境变量配置Ant
    image
  3. 全局系统环境变量配置Git
    image
  4. 配置jenkins报告支持显示HTML样式
    首先在jenkins-系统管理,脚本命令行输入
System.setProperty("hudson.model.DirectoryBrowserSupport.CSP","sandbox; default-src 'self';")
  1. image
    保存后,不是立即生效,需要重新构建下项目,html报告就有显示了

 

常用插件安装

 

由于我们需要显示报告、因此需要安装邮件和第三方报告插件 ,jenkins管理 ->Manager Plugins

 

 

Manage Jenkins ->Manage plugins

 

集成jmeter用例集

 

  1. 新建一个自由风格的项目
  2. 配置构建触发器
    image
  3. 构建执行命令: Execute Windows batch command
    3.1 此处通过命令行简单执行 jmeter生成报告
    image
rd /s/q D:\auto\jtl
rd /s/q D:\auto\report
mkdir jtl
mkdir report
jmeter -n -t  D:\auto\testcase.jmx  -l D:\auto\jtl\result_.jtl -e -o D:\auto\report
exit 0
  1. 3.2 再次新建Invoke Ant ,通过ant build文件构建生成日志
    image
  2. 构建后操作:
    完整显示结构如下:
    image
    Publish HTML reports : 此处展示 简单报告

     

     

     

     


    结果如下显示:
    image
    Publish performance test result report 此处展示性能报告
    image
    结果如下:
    image
  3. 集成邮件配置
    1. 全局系统配置邮件config system
      (1)全局系统管理配置

 

image

(2)全局邮件服务器设置

image

    1. 扩展邮件配置邮件Extended E-mail Notification
      image
      image
    2. 回到项目配置: 添加 构建后操作 -> Editable Email Notification
      image
      image
      完整 邮件报告模板
<!DOCTYPE html>
<html>  
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
<title>53在线接口自动化-第${BUILD_NUMBER}次构建日志</title>  
</head>  
  
<body size="4" leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"  
    offset="0">  
    <table width="95%" cellpadding="0" cellspacing="0"  
        style="font-size: 30pt; font-family: Tahoma, Arial, Helvetica, sans-serif">  
        <tr>  
            <td>(本邮件是程序每天定时下发,有问题请联系测试雍伟业!(公司之后的外网无法打开邮件里的 URL))</td>  
        </tr>  
        <tr>  
            <td><h2>  
                    <font color="#0000FF">构建状态 - ${BUILD_STATUS}</font>  
                </h2></td>  
        </tr>  
        <tr>  
            <td><br />  
            <b><font color="#0B610B">构建信息</font></b>  
            <hr size="3" width="100%" align="center" /></td>  
        </tr>  
        <tr>  
            <td>  
                <ul>  
                    <li>项目名称 : ${PROJECT_NAME}</li>  
                    <li>构建编号 : 第${BUILD_NUMBER}次构建</li>  
                    <li>触发原因: ${CAUSE}</li>  
                    <li>构建日志: <a href="${BUILD_URL}console">${BUILD_URL}console</a></li>  
                    <li >变更集:${JELLY_SCRIPT,template="html"}</a></li>  
 
                    <!-- 下面是报告的位置,根据自己项目要求填写 -->
                    <li>SummaryReport:${FILE, path="D:/demo/log/html/SummaryReport.html"}
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></a></li>  
                </ul>     
                    <hr size="3" width="100%" align="center" />
            </td>  
        </tr>  
    </table>  
</body>  
</html>
    1. 邮箱显示报告如下样式:
      image
      image

 

jmeter相关配置

 

一: 通过简单的命令:构建 目录结构如下

 

csv    &  xml

 

  1. 简单结构目录如下
    image
  2. 修改jmeter.properties文件内容细节
    文件地址
    image

 

  • 设置运行机器为本机
    image
  • 设置报告方式为csv
    image
  • 禁用ssl模式
    image

 

二:通过build文件构建目录如下

 

注意!注意!注意!

 

使用到的jmeter-results-detail-report_21.xsl 文件

 

将build.xml中的第42行

style="${jmeter.home}/extras/jmeter-results-detail-report_21.xsl">

拷贝以下内容将这个路径下的jmeter-results-detail-report_21.xsl文件覆盖,这个文件说明了xsl文件装换为html文件的一些规则

 

使用到的:jmeter.results.shanhe.me.xsl 文件

 

jmeter.results.shanhe.me.xsl

链接:https://pan.baidu.com/s/1TQ7VIEXR9SubNEUZZ3a2xQ

提取码:ne14

 

  1. 文件目录结构
    image
    build文件详细内容如下:

 

<?xml version="1.0" encoding="UTF-8"?>
<project name="ant-jmeter-test" default="run" basedir=".">
    <taskdef resource="net/sf/antcontrib/antlib.xml" />
    <tstamp>
        <!--format property="time" pattern="yyyyMMddkkmm" /-->
        <format property="date" pattern="yyyy/MM/dd kk:mm:ss"/>
        <!--kk是24小时制,KK是12小时制-->
    </tstamp>
    <!-- (1)需要改成自己本地的 Jmeter 目录-->
    <property name="jmeter.home" value="D:/testinstail/xml-jmeter-5.2.1"/>
    <property name="report.title" value="report"/>
    <!-- (2)jmeter生成jtl格式的结果报告的路径-->
    <property name="jmeter.result.jtl.dir" value="D:/demo/log/jtl"/>
    <!-- (3)jmeter生成html格式的结果报告的路径-->
    <property name="jmeter.result.html.dir" value="D:/demo/log/html"/>
    <!-- 生成的报告的前缀 -->
    <property name="ReportName" value="DetailsReport"/>
    <property name="ReportName2" value="SummaryReport" />
    <property name="jmeter.result.jtlName" value="${jmeter.result.jtl.dir}/${ReportName}.jtl"/>
    <property name="jmeter.result.htmlName" value="${jmeter.result.html.dir}/${ReportName}.html"/>
    <property name="jmeter.result.htmlName2" value="${jmeter.result.html.dir}/${ReportName2}.html" />
    <!--项目初始化设置-->
    <target name="init" description="init" >
        <!--删除jtl文件夹下生成的所有文件及文件夹包括空目录,但不删除根目录-->
        <delete verbose="true" includeemptydirs="true" >
            <fileset dir="${jmeter.result.jtl.dir}" >
                <include name="**/*" />
            </fileset>
        </delete>
        <!--删除html文件夹下生成的所有文件及文件夹包括空目录,但不删除根目录-->
        <delete>
            <fileset dir="${jmeter.result.html.dir}">
                <include name="**/*"/>
            </fileset>
        </delete>
        <!--<delete dir="${classes.home}"/><mkdir dir="${classes.home}"/>-->
    </target>
    <target name="run">
        <antcall target="test"/>
        <antcall target="report"/>
        <!--antcall  target="mail"/-->
    </target>
    <target name="test" depends="init">
        <taskdef name="jmeter" classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask"/>
        <jmeter jmeterhome="${jmeter.home}" resultlog="${jmeter.result.jtlName}">
            <!-- (4)build.xml的存放的路径-->
            <testplans dir="D:\demo" includes="*.jmx"/>
            <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" depends="test">
        <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.htmlName}"
   style="${jmeter.home}/extras/jmeter-results-detail-report_21.xsl">
            <param name="titleReport" expression="${report.title}"/>
            <param name="dateReport" expression="${date}"/>
        </xslt>
        <xslt 
   classpathref="xslt.classpath" 
   force="true" 
   in="${jmeter.result.jtlName}"
   out="${jmeter.result.htmlName2}"
   style="${jmeter.home}/extras/jmeter.results.shanhe.me.xsl">
            <param name="titleReport" expression="${report.title}"/>
            <param name="dateReport" expression="${date}"/>
        </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"><for list="hanxm@thunisoft.com" param="tmp" ><sequential><echo>message @{tmp}</echo><mail mailhost="smtp.thunisoft.com" mailport="25" ssl="false" subject="ant mail" messagemimetype="text/html" user="zhangjn" password="*******"  tolist="@{tmp}"><from address="zhangjn@thunisoft.com" /><fileset dir="${jmeter.result.html.dir}"><include name="*.html" /><include name="*.png" /></fileset><message>支持多人同时发邮件!!<br /><br /></message></mail></sequential></for></target-->
</project>

 

  1. jmeter.properties文件配置内容
    文件地址:
    image

 

  • 设置运行机器为本机
  • 设置禁用ssl
  • 设置报告方式为xml
    image

 

邮件报告乱码处理

 

  1. 进入jenkins安装显示目录如下:
    image
  2. 修改指定编码运行jenkins
    image
    运行完以后记得重启生效: https://localhost:8080/restart
  3. 查看jenkins 系统信息编码为UTF-8即操作成功
    image
    注意事项:

如果修改此处的编码方式为utf-8那么 ,**.jmx文件必须为英文 否则构建时由于文件编码不正确会构建失败

 

总结

 

ANT构建脚本 xml

 

1.jmeter脚本准备(不说了)

 

2.新建一个demo,把jmx脚本放进去

 

3.在demo下新建目录resultLog,log下新建两个子目录html,jtl

 

4.将 jmeter的extras目录中ant-jmeter-1.1.1.jar包拷贝至ant安装目录下的lib目录中

 

5.修改Jmeter的bin目录下jmeter.properties文件的配置:jmeter.save.saveservice.output_format=xml

 

html:存放生成的html报告

 

jtl:存放生成的jtl报告

 

build.xml配置

 

<?xml version="1.0" encoding="UTF-8"?>
<project name="ant-jmeter-test" default="run" basedir=".">
    <taskdef resource="net/sf/antcontrib/antlib.xml" />
    <tstamp>
        <!--format property="time" pattern="yyyyMMddkkmm" /-->
        <format property="date" pattern="yyyy/MM/dd kk:mm:ss"/>
        <!--kk是24小时制,KK是12小时制-->
    </tstamp>
    <!-- (1)需要改成自己本地的 Jmeter 目录-->
    <property name="jmeter.home" value="D:/testinstail/xml-jmeter-5.2.1"/>
    <property name="report.title" value="report"/>
    <!-- (2)jmeter生成jtl格式的结果报告的路径-->
    <property name="jmeter.result.jtl.dir" value="D:/demo/log/jtl"/>
    <!-- (3)jmeter生成html格式的结果报告的路径-->
    <property name="jmeter.result.html.dir" value="D:/demo/log/html"/>
    <!-- 生成的报告的前缀 -->
    <property name="ReportName" value="DetailsReport"/>
    <property name="ReportName2" value="SummaryReport" />
    <property name="jmeter.result.jtlName" value="${jmeter.result.jtl.dir}/${ReportName}.jtl"/>
    <property name="jmeter.result.htmlName" value="${jmeter.result.html.dir}/${ReportName}.html"/>
    <property name="jmeter.result.htmlName2" value="${jmeter.result.html.dir}/${ReportName2}.html" />
    <!--项目初始化设置-->
    <target name="init" description="init" >
        <!--删除jtl文件夹下生成的所有文件及文件夹包括空目录,但不删除根目录-->
        <delete verbose="true" includeemptydirs="true" >
            <fileset dir="${jmeter.result.jtl.dir}" >
                <include name="**/*" />
            </fileset>
        </delete>
        <!--删除html文件夹下生成的所有文件及文件夹包括空目录,但不删除根目录-->
        <delete>
            <fileset dir="${jmeter.result.html.dir}">
                <include name="**/*"/>
            </fileset>
        </delete>
        <!--<delete dir="${classes.home}"/><mkdir dir="${classes.home}"/>-->
    </target>
    <target name="run">
        <antcall target="test"/>
        <antcall target="report"/>
        <!--antcall  target="mail"/-->
    </target>
    <target name="test" depends="init">
        <taskdef name="jmeter" classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask"/>
        <jmeter jmeterhome="${jmeter.home}" resultlog="${jmeter.result.jtlName}">
            <!-- (4)build.xml的存放的路径-->
            <testplans dir="D:\demo" includes="*.jmx"/>
            <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" depends="test">
        <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.htmlName}"
   style="${jmeter.home}/extras/jmeter-results-detail-report_21.xsl">
            <param name="titleReport" expression="${report.title}"/>
            <param name="dateReport" expression="${date}"/>
        </xslt>
        <xslt 
   classpathref="xslt.classpath" 
   force="true" 
   in="${jmeter.result.jtlName}"
   out="${jmeter.result.htmlName2}"
   style="${jmeter.home}/extras/jmeter.results.shanhe.me.xsl">
            <param name="titleReport" expression="${report.title}"/>
            <param name="dateReport" expression="${date}"/>
        </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"><for list="xxx@thunisoft.com" param="tmp" ><sequential><echo>message @{tmp}</echo><mail mailhost="smtp.thunisoft.com" mailport="25" ssl="false" subject="ant mail" messagemimetype="text/html" user="xxx" password="*******"  tolist="@{tmp}"><from address="xxx@thunisoft.com" /><fileset dir="${jmeter.result.html.dir}"><include name="*.html" /><include name="*.png" /></fileset><message>支持多人同时发邮件!!<br /><br /></message></mail></sequential></for></target-->
</project>

 

1.修改build.xml中的(1)(2)(3)(4)(5)的路径为自己的响应的路径

 

2.将build.xml中的第42行

 

style="${jmeter.home}/extras/jmeter-results-detail-report_21.xsl">

 

拷贝以下内容将这个路径下的jmeter-results-detail-report_21.xsl文件覆盖,这个文件说明了xsl文件装换为html文件的一些规则

 

jmeter-results-detail-report_21.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="'Load Test Results'"/>
<xsl:param    name="dateReport" select="'date not defined'"/>

<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;
                }
                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;
                }


                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;
                                }


            </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">Date report: <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>Summary</h2>
    <table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
        <tr valign="top">
            <th># Samples</th>
            <th>Failures</th>
            <th>Success Rate</th>
            <th>Average Time</th>
            <th>Min Time</th>
            <th>Max Time</th>
        </tr>
        <tr valign="top">
            <xsl:variable name="allCount" select="count(/testResults/*)" />
            <xsl:variable name="allFailureCount" select="count(/testResults/*[attribute::s='false'])" />
            <xsl:variable name="allSuccessCount" select="count(/testResults/*[attribute::s='true'])" />
            <xsl:variable name="allSuccessPercent" select="$allSuccessCount div $allCount" />
            <xsl:variable name="allTotalTime" select="sum(/testResults/*/@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/*/@t" />
                </xsl:call-template>
            </xsl:variable>
            <xsl:variable name="allMaxTime">
                <xsl:call-template name="max">
                    <xsl:with-param name="nodes" select="/testResults/*/@t" />
                </xsl:call-template>
            </xsl:variable>
            <xsl:attribute name="class">
                <xsl:choose>
                    <xsl:when test="$allFailureCount > 0">Failure</xsl:when>
                </xsl:choose>
            </xsl:attribute>
            <td align="center">
                <xsl:value-of select="$allCount" />
            </td>
            <td align="center">
                <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>Pages</h2>
    <table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
        <tr valign="top">
            <th>URL</th>
            <th># Samples</th>
            <th>Failures</th>
            <th>Success Rate</th>
            <th>Average Time</th>
            <th>Min Time</th>
            <th>Max Time</th>
            <th></th>
        </tr>
        <xsl:for-each select="/testResults/*[not(@lb = preceding::*/@lb)]">
            <xsl:variable name="label" select="@lb" />
            <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 > 0">Failure</xsl:when>
                    </xsl:choose>
                </xsl:attribute>
                <td>
                <xsl:if test="$failureCount > 0">
                  <a><xsl:attribute name="href">#<xsl:value-of select="$label" /></xsl:attribute>
                  <xsl:value-of select="$label" />
                  </a>
                </xsl:if>
                <xsl:if test="0 >= $failureCount">
                  <xsl:value-of select="$label" />
                </xsl:if>
                </td>
                <td align="center">
                    <xsl:value-of select="$count" />
                </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="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="expand/collapse"><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="8" bgcolor="#FF0000">
                              <div align="center">
                     <b>Details for Page "<xsl:value-of select="$label" />"</b>
                     <table bordercolor="#000000" bgcolor="#2674A6" border="0"  cellpadding="1" cellspacing="1" width="95%">
                     <tr>
                        <th>Thread</th>
                        <th>Iteration</th>
                        <th>Time (milliseconds)</th>
                        <th>Bytes</th>
                        <th>Success</th>
                     </tr>
                     <xsl:for-each select="../*[@lb = $label and @tn != $label]">
                        <tr>
                           <td><xsl:value-of select="@tn" /></td>
                           <td align="center"><xsl:value-of select="position()" /></td>
                           <td align="right"><xsl:value-of select="@t" /></td>
                           <!--  TODO allow for missing bytes field -->
                           <td align="right"><xsl:value-of select="@by" /></td>
                           <td align="center"><xsl:value-of select="@s" /></td>
                        </tr>
                     </xsl:for-each>
                     </table>
                  </div>
                           </td>
                        </tr>
        </xsl:for-each>
    </table>
</xsl:template>
<xsl:template name="detail">
    <xsl:variable name="allFailureCount" select="count(/testResults/*[attribute::s='false'])" />
    <xsl:if test="$allFailureCount > 0">
        <h2>Failure Detail</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>

推荐阅读