一、什么是接口測(cè)試?
接口測(cè)試是測(cè)試系統(tǒng)組件間接口的一種測(cè)試。接口測(cè)試主要用于檢測(cè)外部系統(tǒng)與系統(tǒng)之間以及內(nèi)部各個(gè)子系統(tǒng)之間的交互點(diǎn)。測(cè)試的重點(diǎn)是要檢查數(shù)據(jù)的交換,傳遞和控制管理過程,以及系統(tǒng)間的相互邏輯依賴關(guān)系等。?
接口測(cè)試適用于為其他系統(tǒng)提供服務(wù)的底層框架系統(tǒng)和中心服務(wù)系統(tǒng),主要測(cè)試這些系統(tǒng)對(duì)外部提供的接口,驗(yàn)證其正確性和穩(wěn)定性。接口測(cè)試同樣適用于一個(gè)上層系統(tǒng)中的服務(wù)層接口,越往上層,其測(cè)試的難度越大。?
接口測(cè)試實(shí)施在多系統(tǒng)多平臺(tái)的構(gòu)架下,有著極為高效的成本收益比,接口測(cè)試天生為高復(fù)雜性的平臺(tái)帶來高效的缺陷監(jiān)測(cè)和質(zhì)量監(jiān)督能力。平臺(tái)越復(fù)雜,系統(tǒng)越龐大,接口測(cè)試的效果越明顯。
基于接口測(cè)試的重要性,以及它比較容易自動(dòng)化的特性,通過持續(xù)集成的接口監(jiān)控能夠及時(shí)的發(fā)現(xiàn)項(xiàng)目中存在的問題,這對(duì)持續(xù)運(yùn)營(yíng)的項(xiàng)目來說,非常重要。
二、接口測(cè)試的流程
1、 項(xiàng)目啟動(dòng)后,測(cè)試人員要盡早找到開發(fā)人員拿到接口測(cè)試文檔?
2、 獲取接口測(cè)試文檔后,就可以進(jìn)行接口用例的編寫和調(diào)試?
3、 接口用例編寫調(diào)試完成后,部署到持續(xù)集成的測(cè)試環(huán)境中,
4、 設(shè)定腳本運(yùn)行頻率,告警方式等基本參數(shù),進(jìn)行接口的日常監(jiān)控?
5、 每日進(jìn)行接口腳本的維護(hù)更新,接口異常的處理
三、jenkins + ant + jmeter 集成測(cè)試報(bào)告發(fā)送郵件
環(huán)境準(zhǔn)備
安裝Jdk
JDK是Java語言的軟件開發(fā)工具包,主要用于移動(dòng)設(shè)備、嵌入式設(shè)備上的java應(yīng)用程序。JDK是整個(gè)java開發(fā)的核心,它包含了JAVA的運(yùn)行環(huán)境(JVM+Java系統(tǒng)類庫(kù))和JAVA工具。
鼠標(biāo)右擊計(jì)算機(jī)(此電腦)->屬性->高級(jí)系統(tǒng)設(shè)置->高級(jí)->環(huán)境變量
在系統(tǒng)變量中,點(diǎn)擊新建,新建JAVA_HOME變量,變量的值:JDK的安裝目錄

在系統(tǒng)變量中找到Path變量,雙擊打開,新增兩個(gè)變量%JAVA_HOME%\bin和%JAVA_HOME%\jre\bin,點(diǎn)擊確定

在系統(tǒng)變量中新建CLASSPATH變量,變量值:.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar(注意前面的.),點(diǎn)擊確定,保存退出。

檢查是否配置成功,win+R輸入cmd,然后回車,在黑乎乎的窗口輸入java -version,能夠看到你安裝的jdk版本信息,即環(huán)境配置成功。

安裝Ant
ant 是Apache軟件基金會(huì)JAKARTA目錄中的一個(gè)子項(xiàng)目,它有以下的優(yōu)點(diǎn):?
1、跨平臺(tái)性:Ant是純Java語言編寫的,所以具有很好的跨平臺(tái)性。?
2、操作簡(jiǎn)單:Ant是由一個(gè)內(nèi)置任務(wù)和可選任務(wù)組成的,用ant任務(wù)就像是在dos中寫命令行一樣。Ant運(yùn)行時(shí)需要一個(gè)XML文件(構(gòu)建文件)。 Ant通過調(diào)用target樹,就可以執(zhí)行各種task。每個(gè)task實(shí)現(xiàn)了特定接口對(duì)象。
3、維護(hù)簡(jiǎn)單、可讀性好、集成簡(jiǎn)單:由于Ant構(gòu)建文件 時(shí)XML格式的文件,所以很容易維護(hù)和書寫,而且結(jié)構(gòu)很清晰。Ant可以集成到開發(fā)環(huán)境中。由于Ant的跨平臺(tái)性和操作簡(jiǎn)單的特點(diǎn),它很容易集成到一些開 發(fā)環(huán)境中去。
以下是解壓后的目錄布局。
apache-ant-1.10.8
+--- README, LICENSE, fetch.xml, 其他文本文件. //基本信息
+--- bin // 包含安裝程序腳本
|
+--- lib // 包含Ant JARs plus必要的依賴項(xiàng)
|
+--- manual // Ant文檔 (必讀 ;-)
|
+--- etc // 包含xsl工具:
? ? ? ?? // - 可以從xml輸出的各種任務(wù)中創(chuàng)建一個(gè)增強(qiáng)型的報(bào)告。
? ? ? ?? // - 遷移你的構(gòu)建文件,并擺脫 "已廢棄 "的警告
? ? ? ?? // - ... 更多 ;-)
點(diǎn)擊http://ant.apache.org/bindownload.cgi進(jìn)入ant官網(wǎng),下載對(duì)應(yīng)的安裝包。

將下載的.zip壓縮包解壓到對(duì)應(yīng)文件夾
配置環(huán)境變量
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
驗(yàn)證是否安裝成功
依次選擇:win + R –>cmd,輸入如下命令:ant? ,出現(xiàn)如下圖,則表示安裝成功

安裝jenkins
jenkins有三種安裝方式
第一種:快速安裝選擇windows系統(tǒng)的版本

解壓成功后雙擊jenkins.msi程序

安裝成功后會(huì)顯示如下要你填寫密碼的驗(yàn)證頁面,按照它的提示信息到對(duì)應(yīng)的目錄底下找文件initialAdminPassword,然后將密碼拷貝出來? localhost:8080

第二種:快速安裝 使用命令 java -jar jenkins.war這是依賴于 java環(huán)境和 jenkins.war進(jìn)行搭建這里不多說,因?yàn)楹竺娴陌惭b順序都是和上述一致
第三種方法:
是直接將jenkins.war包安裝在tomcat的webapps目錄下,然后啟動(dòng)tomcatcat就可以了,當(dāng)然Tomcat也有兩種啟動(dòng)方式。但原理都是一樣的。只是看誰比較方便,兼容性比較強(qiáng)而已。關(guān)鍵還是看系統(tǒng) st
startup.sh?
總結(jié):三種安裝方式都使用與Windows系統(tǒng),第二種和第三種可以使用在linux系統(tǒng),但是為求不出錯(cuò),第二種才是最方便的。如果直接將jenkins.war包放到Tomcat的webapps下,那你公司的項(xiàng)目也放到這里,那就好玩了。
此處, 我們選擇第一種方式進(jìn)行安裝
配置jmeter變量
官網(wǎng)下載

解壓任意目錄即可
配置環(huán)境變量
點(diǎn)擊“新建”,建立一個(gè)變量:JMETER_HOME,值為你解壓的jmeter安裝路徑。我的安裝路徑是在C盤,這個(gè)路徑根據(jù)自己實(shí)際安裝路徑進(jìn)行填寫。然后點(diǎn)擊確定保存即可

配置classpath變量 ;
%JMETER_HOME%\lib\ext\ApacheJMeter_core.jar;%JMETER_HOME%\lib\jorphan.jar;%JMETER_HOME%\lib/logkit-2.0.jar

在用系統(tǒng)變量path后面加上%JMETER_HOME%\bin

最后在cmd輸入jmeter 直接打開 如圖
配置jenkins
環(huán)境變量配置
全局系統(tǒng)環(huán)境變量配置JDK

全局系統(tǒng)環(huán)境變量配置Ant

全局系統(tǒng)環(huán)境變量配置Git

配置jenkins報(bào)告支持顯示HTML樣式
首先在jenkins-系統(tǒng)管理,腳本命令行輸入
System.setProperty("hudson.model.DirectoryBrowserSupport.CSP","sandbox; default-src 'self';")

保存后,不是立即生效,需要重新構(gòu)建下項(xiàng)目,html報(bào)告就有顯示了
常用插件安裝
由于我們需要顯示報(bào)告、因此需要安裝郵件和第三方報(bào)告插件 ,jenkins管理 ->Manager Plugins
Ant Plugin
Manage Jenkins ->Manage plugins
集成jmeter用例集
新建一個(gè)自由風(fēng)格的項(xiàng)目
配置構(gòu)建觸發(fā)器

構(gòu)建執(zhí)行命令: Execute Windows batch command
3.1 此處通過命令行簡(jiǎn)單執(zhí)行 jmeter生成報(bào)告

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
3.2 再次新建Invoke Ant ,通過ant build文件構(gòu)建生成日志

構(gòu)建后操作:
完整顯示結(jié)構(gòu)如下:

Publish HTML reports : 此處展示 簡(jiǎn)單報(bào)告
結(jié)果如下顯示:

Publish performance test result report 此處展示性能報(bào)告

結(jié)果如下:

集成郵件配置
全局系統(tǒng)配置郵件config system
(1)全局系統(tǒng)管理配置

? (2)全局郵件服務(wù)器設(shè)置

擴(kuò)展郵件配置郵件Extended E-mail Notification


回到項(xiàng)目配置: 添加 構(gòu)建后操作 -> Editable Email Notification


完整 郵件報(bào)告模板
<!DOCTYPE html>
<html> ?
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> ?
<title>53在線接口自動(dòng)化-第${BUILD_NUMBER}次構(gòu)建日志</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>(本郵件是程序每天定時(shí)下發(fā),有問題請(qǐng)聯(lián)系測(cè)試Young?。ü局蟮耐饩W(wǎng)無法打開郵件里的 URL))</td> ?
? ? ?? </tr> ?
? ? ?? <tr> ?
? ? ? ? ?? <td><h2> ?
? ? ? ? ? ? ? ? ?? <font color="#0000FF">構(gòu)建狀態(tài) - ${BUILD_STATUS}</font> ?
? ? ? ? ? ? ?? </h2></td> ?
? ? ?? </tr> ?
? ? ?? <tr> ?
? ? ? ? ?? <td><br /> ?
? ? ? ? ?? <b><font color="#0B610B">構(gòu)建信息</font></b> ?
? ? ? ? ?? <hr size="3" width="100%" align="center" /></td> ?
? ? ?? </tr> ?
? ? ?? <tr> ?
? ? ? ? ?? <td> ?
? ? ? ? ? ? ?? <ul> ?
? ? ? ? ? ? ? ? ?? <li>項(xiàng)目名稱 : ${PROJECT_NAME}</li> ?
? ? ? ? ? ? ? ? ?? <li>構(gòu)建編號(hào) : 第${BUILD_NUMBER}次構(gòu)建</li> ?
? ? ? ? ? ? ? ? ?? <li>觸發(fā)原因: ${CAUSE}</li> ?
? ? ? ? ? ? ? ? ?? <li>構(gòu)建日志: <a href="${BUILD_URL}console">${BUILD_URL}console</a></li> ?
? ? ? ? ? ? ? ? ?? <li >變更集:${JELLY_SCRIPT,template="html"}</a></li> ?
? ? ? ? ? ? ? ? ?? <!-- 下面是報(bào)告的位置,根據(jù)自己項(xiàng)目要求填寫 -->
? ? ? ? ? ? ? ? ?? <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>
郵箱顯示報(bào)告如下樣式:

jmeter相關(guān)配置? ?
一: 通過簡(jiǎn)單的命令:構(gòu)建 目錄結(jié)構(gòu)如下
csv? ? &? xml
簡(jiǎn)單結(jié)構(gòu)目錄如下

修改jmeter.properties文件內(nèi)容細(xì)節(jié)
文件地址

設(shè)置運(yùn)行機(jī)器為本機(jī)

設(shè)置報(bào)告方式為csv

禁用ssl模式

二:通過build文件構(gòu)建目錄如下
? 注意!注意!注意!
使用到的jmeter-results-detail-report_21.xsl 文件
將build.xml中的第42行
style="${jmeter.home}/extras/jmeter-results-detail-report_21.xsl">
拷貝以下內(nèi)容將這個(gè)路徑下的jmeter-results-detail-report_21.xsl文件覆蓋,這個(gè)文件說明了xsl文件裝換為html文件的一些規(guī)則
使用到的:jmeter.results.shanhe.me.xsl 文件
jmeter.results.shanhe.me.xsl
鏈接:https://pan.baidu.com/s/1TQ7VIEXR9SubNEUZZ3a2xQ 提取碼:ne14
文件目錄結(jié)構(gòu)
build文件詳細(xì)內(nèi)容如下:

<?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小時(shí)制,KK是12小時(shí)制-->
?? </tstamp>
?? <!-- (1)需要改成自己本地的 Jmeter 目錄-->
?? <property name="jmeter.home" value="D:/testinstail/xml-jmeter-5.2.1"/>
?? <property name="report.title" value="report"/>
?? <!-- (2)jmeter生成jtl格式的結(jié)果報(bào)告的路徑-->
?? <property name="jmeter.result.jtl.dir" value="D:/demo/log/jtl"/>
?? <!-- (3)jmeter生成html格式的結(jié)果報(bào)告的路徑-->
?? <property name="jmeter.result.html.dir" value="D:/demo/log/html"/>
?? <!-- 生成的報(bào)告的前綴 -->
?? <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" />
?? <!--項(xiàng)目初始化設(shè)置-->
?? <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="dateReport" expression="${date}"/>
? ? ?? </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="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="Young@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="Young" password="*******"? tolist="@{tmp}"><from address="Young@thunisoft.com" /><fileset dir="${jmeter.result.html.dir}"><include name="*.html" /><include name="*.png" /></fileset><message>支持多人同時(shí)發(fā)郵件!!<br /><br /></message></mail></sequential></for></target-->
</project>
jmeter.properties文件配置內(nèi)容
文件地址:

設(shè)置運(yùn)行機(jī)器為本機(jī)
設(shè)置禁用ssl
設(shè)置報(bào)告方式為xml

郵件報(bào)告亂碼處理
進(jìn)入jenkins安裝顯示目錄如下:

修改指定編碼運(yùn)行jenkins
運(yùn)行完以后記得重啟生效: https://localhost:8080/restart

查看jenkins 系統(tǒng)信息編碼為UTF-8即操作成功

注意事項(xiàng):
如果修改此處的編碼方式為utf-8那么 ,**.jmx文件必須為英文 否則構(gòu)建時(shí)由于文件編碼不正確會(huì)構(gòu)建失敗
總結(jié)
ANT構(gòu)建腳本 xml
1.jmeter腳本準(zhǔn)備(不說了)
2.新建一個(gè)demo,把jmx腳本放進(jìn)去
3.在demo下新建目錄resultLog,log下新建兩個(gè)子目錄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報(bào)告
jtl:存放生成的jtl報(bào)告
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小時(shí)制,KK是12小時(shí)制-->
?? </tstamp>
?? <!-- (1)需要改成自己本地的 Jmeter 目錄-->
?? <property name="jmeter.home" value="D:/testinstail/xml-jmeter-5.2.1"/>
?? <property name="report.title" value="report"/>
?? <!-- (2)jmeter生成jtl格式的結(jié)果報(bào)告的路徑-->
?? <property name="jmeter.result.jtl.dir" value="D:/demo/log/jtl"/>
?? <!-- (3)jmeter生成html格式的結(jié)果報(bào)告的路徑-->
?? <property name="jmeter.result.html.dir" value="D:/demo/log/html"/>
?? <!-- 生成的報(bào)告的前綴 -->
?? <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" />
?? <!--項(xiàng)目初始化設(shè)置-->
?? <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="dateReport" expression="${date}"/>
? ? ?? </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="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="Young@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="Young" password="*******"? tolist="@{tmp}"><from address="Young@thunisoft.com" /><fileset dir="${jmeter.result.html.dir}"><include name="*.html" /><include name="*.png" /></fileset><message>支持多人同時(shí)發(fā)郵件!!<br /><br /></message></mail></sequential></for></target-->
</project>
1.修改build.xml中的(1)(2)(3)(4)(5)的路徑為自己的響應(yīng)的路徑
2.將build.xml中的第42行
style="${jmeter.home}/extras/jmeter-results-detail-report_21.xsl">
拷貝以下內(nèi)容將這個(gè)路徑下的jmeter-results-detail-report_21.xsl文件覆蓋,這個(gè)文件說明了xsl文件裝換為html文件的一些規(guī)則
jmeter-results-detail-report_21.xsl 文件內(nèi)容如下:
<?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 >JMeter</a> and <a >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>