Selenium+TestNG Web自动化测试环境搭建9_ANT自动化执行以及testNG报告优化

1)利用ANT来自动化执行测试用例,并优化testNG报告

TestNG有三种运行测试用例的方式:

  1、使用testng.xml文件

  2、使用ant

  3、使用命令行的方式

这里介绍下前两种方式。


下载testNG-xslt(用于优化testNG报告):

1. 下载地址:http://www.antepedia.com/detail/p/testng-xslt.html
2. 解压后把saxon-8.7.jar放到project的libs目录下
3. 然后再把testng-results.xsl 放到工程的test-output 目录下


安装ANT:

下载地址:http://ant.apache.org/

下载1.9.7后, 解压到某个目录;

添加环境变量ANT_HOME,在系统变量PATH里面添加%ANT_HOME%\bin;

根据需要,下载相关jar包,放到lib里面。


配置ANT:

生成build.xml 和testng.xml(方法见本文附录);

配置testng.xml:

这里,按class来批量跑case。testNG还可以按包(package)和组(group)来跑case。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="classes">
  <test name="Test">
    <classes>
      <class name="common.ScreenShort"/>
      <class name="testBD.TestHighlight"/>
      <class name="testBD.A123"/>
      <class name="testBD.testBD"/>
      <class name="common.InitialDriver"/>
      <class name="testBD.test1"/>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->

说明:配置好testng.xml后,我们直接右键testng.xml, Run As --->TestNG Suit 即可按所配置的来批量跑cases。

配置build.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- WARNING: Eclipse auto-generated file.
              Any modifications will be overwritten.
              To include a user specific buildfile here, simply create one in the same
              directory with the processing instruction <?eclipse.ant.import?>
              as the first entry and export the buildfile again. -->
<project basedir="." default="build" name="webTest">
	<property environment="env"/>
	<property name="AntHome" value="C:\Tools\apache-ant-1.9.7"/>
	<property name="ECLIPSE_HOME" value="C:/Tools/eclipse-luna-with-plugin/eclipse/"/>
	<property name="debuglevel" value="source,lines,vars"/>
	<property name="target" value="1.7"/>
	<property name="source" value="1.7"/>
	<path id="AntHome.classpath">
<span style="color:#ff0000;">		<fileset dir="${AntHome}/lib/">
			<include name="*.jar"/>
		</fileset></span>
	</path>
	<target name="init">
		<mkdir dir="target/test-classes"/>
		<mkdir dir="target/classes"/>
		<copy includeemptydirs="false" todir="target/test-classes">
			<fileset dir="src/test/java">
				<exclude name="**/*.java"/>
			</fileset>
		</copy>
		<copy includeemptydirs="false" todir="target/classes">
			<fileset dir="src/main/java">
				<exclude name="**/*.java"/>
			</fileset>
		</copy>
	</target>
	<target name="clean">
		<delete dir="target/test-classes"/>
		<delete dir="target/classes"/>
	</target>
	<target depends="clean" name="cleanall"/>
	<target depends="build-subprojects,build-project" name="build"/>
	<target name="build-subprojects"/>
	<target depends="init" name="build-project">
		<echo message="${ant.project.name}: ${ant.file}"/>
		<javac debug="true" debuglevel="${debuglevel}" destdir="target/test-classes" includeantruntime="false" source="${source}" target="${target}" <span style="color:#ff0000;">encoding="UTF-8"</span>>
			<src path="src/test/java"/>
			<classpath refid="webTest.classpath"/>
		</javac>
		<javac debug="true" debuglevel="${debuglevel}" destdir="target/classes" includeantruntime="false" source="${source}" target="${target}" <span style="color:#ff0000;">encoding="UTF-8"</span>>
			<src path="src/main/java"/>
			<classpath refid="webTest.classpath"/>
		</javac>
	</target>
	<target description="Build all projects which reference this project. Useful to propagate changes." name="build-refprojects"/>
	<target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler">
		<copy todir="${ant.library.dir}">
			<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
		</copy>
		<unzip dest="${ant.library.dir}">
			<patternset includes="jdtCompilerAdapter.jar"/>
			<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
		</unzip>
	</target>
	<target description="compile project with Eclipse compiler" name="build-eclipse-compiler">
		<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
		<antcall target="build"/>
	</target>
	<!-- Config for testng -->
	<taskdef name="testng" classname="org.testng.TestNGAntTask">
		<classpath>
			<pathelement location="${AntHome}/lib/testng/testng/6.8/testng-6.8.jar"/>
		</classpath>
	</taskdef>
	<!-- execute testng after compile, then generate report -->
<span style="color:#ff0000;">	<target name="Run">
		<!-- config testng -->
		<testng outputdir="${basedir}" useDefaultListeners="true">
			<!-- execute testcase follow testng.xml -->
			<classpath refid="webTest.classpath"/>
			<xmlfileset dir="." includes="testng.xml"/>
			<!-- generate report title -->
			<sysproperty key="org.uncommons.reportng.title" value="Test Automation"/>
			<sysproperty key="org.uncommons.reportng.escape-output" value="false"/>
		</testng>
	</target>
	<target name="transform">
		<xslt in="${basedir}/test-output/testng-results.xml" style="${basedir}/test-output/testng-results.xsl" out="${basedir}/test-output/xsltresult.html" processor="SaxonLiaison">
			<!-- you need to specify the directory here again -->
			<param name="testNgXslt.outputDir" expression="${basedir}/test-output/"/>
			<classpath refid="AntHome.classpath"/>
		</xslt>
	</target></span>
</project>
每个人的工程不一样,生成的build.xml会稍有差别。

强调一下以下几点:(自己根据生成的build.xml做的修改)

		<fileset dir="${AntHome}/lib/">
			<include name="*.jar"/>
		</fileset>
这个是说引入AntHome/lib路径下所有的jar文件;

在javac里面加encoding="UTF-8"是为了设置编码格式,因为要跑的case里面有中文字符;

还要在Eclipse里面设置UTF-8编码:右键build.xml, 选择Run As--->External Tools Configration...--->Common--->Encoding, 选择UTF-8,如下图:




TestNG报告的优化:

后面两个target就是testNG相关的了:

name="Run"这个target是为了跑testng.xml里面配置的class。

name="transfer"这个target是为了优化testNG的报告。

说明:这里把testng.xml配置到build.xml里面是为了让批量跑case和生成优化报告一次完成。

(你也可以不配置name="Run"这个target,执行的时候,先运行testng.xml完成case的批量执行,再运行build.xml完成报告的优化)


默认情况下,在工程的test-output目录,testNG会生成两种html的报告:index.html和emailable-report.html

比如之前的例子,执行完会有下面两种报告:


这两种报告都不够美观。

生成优化后的TestNG报告:

配置好build.xml后,右键, Run AS--->Ant Build。控制台可以看到以下输出:

.................

Run:
      [testng] Starting ChromeDriver (v2.9.248315) on port 17652
      [testng] [TestNG] Running:
      [testng]   H:\work\workspace\webTest\testng.xml
      [testng] ===============================================
      [testng] Suite
      [testng] Total tests run: 5, Failures: 1, Skips: 1
      [testng] ===============================================
      [testng] The tests failed.
BUILD SUCCESSFUL
Total time: 1 minute 8 seconds

有BUILD SUCCESSFUL说明执行成功。

(注意:本人执行的过程中会报各种classnotfound的错误, 那是因为相关jar包没有下载的原因,只要按提示下载相关jar包, 放到AntHome/lib下面即可)

来看优化后的报告:

根据build.xml的配置,在test-output下面会生成xsltresult.html,这个就是优化后的报告:

1)首先它带有Failed,Passed和Skipped的统计(图):


2)查看细节:

点击上图的左下方的Test,勾选Group by class:

会看到更详细的执行信息:Passed的方法会标绿;Failed的方法会标红;Skipped的方法会标黄;对于fail的case, 点击对应标红的信息即能看到fail的具体信息。

(点击Results overview 会切换到上面的统计图模式)



至此,就完成了testNG 用例的批量执行(配置testNG.xml)以及testNG报告的优化(结合Ant的build.xml)


附:利用Eclipse生成一些xml的方法

(网上很多做法都是自己去创建xml, 然后进行配置, 其实Eclipse都有生成这些xml的方法,小结如下)

TestNG:  Eclipse生成testng.xml: 在工程上右键,选择TestNG --->Convert to TestNG;

Maven:   Eclipse生成pom.xml: 在工程上右键,选择Configure ---> Convert to Maven Project;

Ant:         Eclipse生成build.xml: 在工程上右键,选择Export... ---> General ---> Ant Buildfiles;



eclipse-testng 离线包<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://exslt.org/math" xmlns:testng="http://testng.org"> <xsl:output method="html" indent="yes" omit-xml-declaration="yes" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/> <xsl:output name="text" method="text"/> <xsl:output name="xml" method="xml" indent="yes"/> <xsl:output name="html" method="html" indent="yes" omit-xml- declaration="yes"/> <xsl:output name="xhtml" method="xhtml" indent="yes" omit-xml-declaration="yes"/> <xsl:param name="testNgXslt.outputDir"/> <xsl:param name="testNgXslt.cssFile"/> <xsl:param name="testNgXslt.showRuntimeTotals"/> <xsl:param name="testNgXslt.reportTitle"/> <xsl:param name="testNgXslt.sortTestCaseLinks"/> <xsl:param name="testNgXslt.chartScaleFactor"/> <!-- FAIL,PASS,SKIP,CONF,BY_CLASS--> <xsl:param name="testNgXslt.testDetailsFilter"/> <xsl:variable name="testDetailsFilter" select="if ($testNgXslt.testDetailsFilter) then $testNgXslt.testDetailsFilter else 'FAIL,PASS,SKIP'"/> <xsl:variable name="chartWidth" select="round(600 * testng:getVariableSafe($testNgXslt.chartScaleFactor, 1))"/> <xsl:variable name="chartHeight" select="round(200 * testng:getVariableSafe($testNgXslt.chartScaleFactor, 1))"/> <xsl:template name="writeCssFile"> <xsl:result- document href="{testng:absolutePath('style.css')}" format="text"> <xsl:choose> <xsl:when test="testng:isFilterSelected('CONF') = 'true'"> .testMethodStatusCONF { } </xsl:when> <xsl:otherwise> .testMethodStatusCONF { display: none; } </xsl:otherwise> </xsl:choose> <xsl:choose> <xsl:when test="testng:isFilterSelected('FAIL') = 'true'"> .testMethodStatusFAIL { background-color: #FFBBBB; } </xsl:when> <xsl:otherwise> .testMethodStatusFAIL { background-color: #FFBBBB; display: none; } </xsl:otherwise> </xsl:choose> <xsl:choose> <xsl:when test="testng:isFilterSelected ('PASS') = 'true'"> .testMethodStatusPASS { background-color: lightgreen; } </xsl:when> <xsl:otherwise> .testMethodStatusPASS { background-color: lightgreen; display: none; } </xsl:otherwise> </xsl:choose> <xsl:choose> <xsl:when test="testng:isFilterSelected('SKIP') = 'true'"> .testMethodStatusSKIP { background-color: #FFFFBB; } </xsl:when> <xsl:otherwise> .testMethodStatusSKIP { background-color: #FFFFBB; display: none; } </xsl:otherwise> </xsl:choose> <![CDATA[ body { font-family: Arial, sans-serif; font-size: 12px; padding: 10px; margin: 0px; background-color: white; } a, a:hover, a:active, a:visited { color: navy; } .suiteMenuHeader { margin-top: 10px; } .suiteMenuHeader td { padding: 5px; background-color: #e0e0e0; font-size: 12px; width: 100%; vertical-align: top; } .suiteStatusPass, .suiteStatusFail { padding-right: 20px; width: 20px; height: 20px; margin: 2px 4px 2px 2px; display: inline; } .suiteStatusPass { background-color: green; } .suiteStatusFail { background-color: red; } .testCaseLink, .testCaseLinkSelected { margin-top: 2px; padding: 4px; cursor: pointer; } .testCaseLink { background-color: #f6f6f6; } .testCaseLinkSelected { background-color: lightblue; border: 1px solid gray; padding: 3px; } .testCaseFail, .testCasePass, .testCaseSkip { padding-right: 15px; width: 15px; height: 15px; margin: 2px 4px 2px 2px; display: inline; } .testCaseFail { background-color: red; } .testCasePass { background-color: green; } .testCaseSkip { background-color: yellow; } tr.methodsTableHeader { background-color: #eaf0f7; font-weight: bold; } tr.methodsTableHeader td { padding: 3px; } .testMethodStatusFAIL a, .testMethodStatusPASS a, .testMethodStatusSKIP a { color:navy; text-decoration: none; cursor: pointer; } .testMethodStatusFAIL td, .testMethodStatusPASS td, .testMethodStatusSKIP td { padding: 3px; } .testMethodDetails, .testMethodDetailsVisible { padding: 5px; background-color: #f5f5f5; margin: 1px; } .testMethodDetails { display: none; } .testMethodsTable { margin-top: 10px; font-size: 12px; } .testMethodsTable td { border-width: 1px 0 0 1px; border-color: white; border-style:solid; } .testMethodsTable .testMethodStatusCONF td.firstMethodCell { border-left: 5px solid gray; } ]]> </xsl:result-document> </xsl:template> <xsl:template name="writeJsFile"> <xsl:result-document href="{testng:absolutePath('main.js')}" format="text"> <![CDATA[ var selectedTestCaseLink; function clearAllSelections() { if (selectedTestCaseLink != null) { selectedTestCaseLink.className = "testCaseLink"; } } function selectTestCaseLink(testCaseLinkElement) { clearAllSelections(); testCaseLinkElement.className = "testCaseLinkSelected"; selectedTestCaseLink = testCaseLinkElement; } function switchTestMethodsView(checkbox) { document.getElementById ("testMethodsByStatus").style["display"] = checkbox.checked ? "none" : "block"; document.getElementById ("testMethodsByClass").style["display"] = checkbox.checked ? "block" : "none"; } function toggleVisibility(elementId) { var displayElement = document.getElementById(elementId); if (getCurrentStyle(displayElement, "display") == "none") { displayElement.style["display"] = "block"; } else { displayElement.style["display"] = "none"; } } function toggleDetailsVisibility(elementId) { var displayElement = document.getElementById(elementId); if (displayElement.className == "testMethodDetails") { displayElement.className = "testMethodDetailsVisible"; } else { displayElement.className = "testMethodDetails"; } } function getCurrentStyle(elem, prop) { if (elem.currentStyle) { var ar = prop.match(/\w[^-]*/g); var s = ar[0]; for(var i = 1; i < ar.length; ++i) { s += ar[i].replace(/\w/, ar[i].charAt(0).toUpperCase()); } return elem.currentStyle[s]; } else if (document.defaultView.getComputedStyle) { return document.defaultView.getComputedStyle(elem, null).getPropertyValue(prop); } } function testMethodsFilterChanged(filterCheckBox, status) { var filterAll = document.getElementById ("methodsFilter_ALL"); var filterFail = document.getElementById("methodsFilter_FAIL"); var filterPass = document.getElementById("methodsFilter_PASS"); var filterSkip = document.getElementById ("methodsFilter_SKIP"); var filterConf = document.getElementById("methodsFilter_CONF"); if (filterCheckBox != filterAll) { filterMethods(filterCheckBox, status); checkMainFilter(filterAll, filterFail, filterPass, filterSkip, filterConf); } else { filterFail.checked = filterPass.checked = filterSkip.checked = filterConf.checked = filterAll.checked; filterMethods(filterAll, "FAIL"); filterMethods(filterAll, "PASS"); filterMethods (filterAll, "SKIP"); filterMethods(filterAll, "CONF"); } closeAllExpandedDetails(); } function checkMainFilter(filterAll, filterFail, filterPass, filterSkip, filterConf) { if ((filterFail.checked == filterPass.checked) && (filterPass.checked == filterSkip.checked) && (filterSkip.checked == filterConf.checked)) { filterAll.checked = filterFail.checked; } else { filterAll.checked = false; } } function filterMethods (filterCheckBox, status) { var visible = filterCheckBox.checked; alterCssElement ("testMethodStatus" + status, "display", visible ? "" : "none"); } function alterCssElement(cssClass, element, value) { var rules; if (document.all) { rules = 'rules'; } else if (document.getElementById) { rules = 'cssRules'; } for (var i = 0; i < document.styleSheets.length; i++) { for (var j = 0; j < document.styleSheets [i][rules].length; j++) { if (document.styleSheets[i][rules][j].selectorText.indexOf(cssClass) > -1) { document.styleSheets[i][rules][j].style[element] = value; break; } } } } function closeAllExpandedDetails() { var node = document.getElementsByTagName("body")[0]; //var re = new RegExp("\ \btestMethodDetailsVisible\\b"); var els = document.getElementsByTagName("div"); for (var i = 0,j = els.length; i < j; i++) { if (els[i].className == "testMethodDetailsVisible") { els[i].className = "testMethodDetails"; } } } function renderSvgEmbedTag(chartWidth, chartHeight) { var success = false; var userAgent = navigator.userAgent; if (userAgent.indexOf("Firefox") > -1 || userAgent.indexOf("Safari") > -1) { success = true; } else if (navigator.mimeTypes != null && navigator.mimeTypes.length > 0) { if (navigator.mimeTypes["image/svg+xml"] != null) { success = true; } } else if (window.ActiveXObject) { try { testObj = new ActiveXObject("Adobe.SVGCtl"); success = true; } catch (e) {} } var chartContainer = document.getElementById('chart-container'); if (success) { var chart = document.createElement('embed'); chart.src = 'overview-chart.svg'; chart.type = 'image/svg+xml'; chart.width = chartWidth; chart.height = chartHeight; chartContainer.appendChild(chart); } else { var message = document.createElement('h4'); var text = document.createTextNode('SVG Pie Charts are not available. Please install a SVG viewer for your browser.'); message.style.color = 'navy'; message.appendChild(text); chartContainer.appendChild(message); } } ]]> </xsl:result- document> </xsl:template> <xsl:template name="htmlHead"> <head> <title> <xsl:value- of select="testng:getVariableSafe($testNgXslt.reportTitle, 'TestNG Results')"/> </title> <meta http- equiv="content-type" content="text/html; charset=utf-8"/> <meta http-equiv="pragma" content="no-cache"/> <meta http-equiv="cache-control" content="max-age=0"/> <meta http-equiv="cache-control" content="no-cache"/> <meta http-equiv="cache-control" content="no-store"/> <LINK rel="stylesheet" href="style.css"/> <xsl:if test="$testNgXslt.cssFile"> <LINK rel="stylesheet" href="{$testNgXslt.cssFile}"/> </xsl:if> <script type="text/javascript" src="main.js"/> </head> </xsl:template> <xsl:function name="testng:getVariableSafe"> <xsl:param name="testVar"/> <xsl:param name="defaultValue"/> <xsl:value-of select="if ($testVar) then $testVar else $defaultValue"/> </xsl:function> <xsl:function name="testng:trim"> <xsl:param name="arg"/> <xsl:sequence select="replace(replace($arg,'\s+$',''),'^\s +','')"/> </xsl:function> <xsl:function name="testng:absolutePath"> <xsl:param name="fileName"/> <xsl:value-of select="concat('file:////', $testNgXslt.outputDir, '/', $fileName)"/> </xsl:function> <xsl:function name="testng:safeFileName"> <xsl:param name="fileName"/> <xsl:value-of select="translate($fileName, '[]{}`~! @#$%^*(){};?/\|' , '______________________')"/> </xsl:function> <xsl:function name="testng:suiteContentFileName"> <xsl:param name="suiteElement"/> <xsl:value-of select="testng:safeFileName(concat($suiteElement/@name, '.html'))"/> </xsl:function> <xsl:function name="testng:suiteGroupsFileName"> <xsl:param name="suiteElement"/> <xsl:value-of select="testng:safeFileName(concat($suiteElement/@name, '_groups.html'))"/> </xsl:function> <xsl:function name="testng:testCaseContentFileName"> <xsl:param name="testCaseElement"/> <xsl:value-of select="testng:safeFileName(concat($testCaseElement/../@name, '_', $testCaseElement/@name, '.html'))"/> </xsl:function> <xsl:function name="testng:concatParams"> <xsl:param name="params"/> <xsl:variable name="outputString"> <xsl:value-of separator="," select="for $i in ($params) return $i"/> </xsl:variable> <xsl:value-of select="$outputString"/> </xsl:function> <xsl:function name="testng:testMethodStatus"> <xsl:param name="testMethodElement"/> <xsl:variable name="status" select="$testMethodElement/@status"/> <xsl:variable name="statusClass" select="concat('testMethodStatus', $status)"/> <xsl:value-of select="if ($testMethodElement/@is-config) then concat($statusClass, ' testMethodStatusCONF') else $statusClass"/> </xsl:function> <xsl:function name="testng:suiteMethodsCount"> <xsl:param name="testCasesElements"/> <xsl:param name="state"/> <xsl:value-of select="if ($state = '*') then count($testCasesElements/class/test- method[not(@is-config)]) else count($testCasesElements/class/test-method[(@status=$state) and (not(@is-config))])"/> </xsl:function> <xsl:function name="testng:testCaseMethodsCount"> <xsl:param name="testCaseElement"/> <xsl:param name="state"/> <xsl:value-of select="if ($state = '*') then count ($testCaseElement/class/test-method[not(@is-config)]) else count($testCaseElement/class/test-method[(@status=$state) and (not(@is-config))])"/> </xsl:function> <xsl:function name="testng:suiteStateClass"> <xsl:param name="testCaseElements"/> <xsl:value-of select="if (count($testCaseElements/class/test-method[(@status='FAIL') and (not(@is-config))]) > 0) then 'suiteStatusFail' else 'suiteStatusPass'"/> </xsl:function> <xsl:function name="testng:methodsDuration"> <xsl:param name="testMethods"/> <xsl:variable name="durationMs" select="sum ($testMethods/@duration-ms)"/> <xsl:value-of select="testng:formatDuration($durationMs)"/> </xsl:function> <xsl:function name="testng:formatDuration"> <xsl:param name="durationMs"/> <!--Days--> <xsl:if test="$durationMs > 86400000"> <xsl:value-of select="format-number($durationMs div 86400000, '#')"/>d </xsl:if> <!--Hours--> <xsl:if test="($durationMs > 3600000) and ($durationMs mod 86400000 > 1000)"> <xsl:value-of select="format-number(($durationMs mod 86400000) div 3600000, '#')"/>h </xsl:if> <xsl:if test="$durationMs < 86400000"> <!--Minutes--> <xsl:if test="($durationMs > 60000) and ($durationMs mod 3600000 > 1000)"> <xsl:value-of select="format-number(($durationMs mod 3600000) div 60000, '#')"/>m </xsl:if> <!--Seconds--> <xsl:if test="($durationMs > 1000) and ($durationMs mod 60000 > 1000)"> <xsl:value-of select="format-number(($durationMs mod 60000) div 1000, '#')"/>s </xsl:if> </xsl:if> <!--Milliseconds - only when less than a second--> <xsl:if test="$durationMs < 1000"> <xsl:value-of select="$durationMs"/> ms </xsl:if> </xsl:function> <xsl:function name="testng:isFilterSelected"> <xsl:param name="filterName"/> <xsl:value-of select="contains ($testDetailsFilter, $filterName)"/> </xsl:function> <xsl:template name="formField"> <xsl:param name="label"/> <xsl:param name="value"/> <xsl:if test="$value"> <div> <b> <xsl:value-of select="$label"/>: </b> <xsl:value-of select="$value"/> </div> </xsl:if> </xsl:template> <xsl:template name="formFieldList"> <xsl:param name="label"/> <xsl:param name="value"/> <xsl:if test="count($value) > 0"> <div> <b> <xsl:value- of select="$label"/>: </b> <xsl:for-each select="$value"> <div>     - <xsl:value-of select="."/> </div> </xsl:for-each> </div> </xsl:if> </xsl:template> <xsl:template match="/testng-results"> <xsl:call-template name="writeCssFile"/> <xsl:call-template name="writeJsFile"/> <html> <xsl:call-template name="htmlHead"/> <frameset cols="250px, 100%" frameborder="1"> <frame name="navigation" src="navigation.html"/> <frame name="content" src="overview.html"/> </frameset> </html> <xsl:variable name="suiteElements" select="if (suite/@url) then document(suite/@url)/suite else suite"/> <xsl:call-template name="navigationFile"> <xsl:with-param name="suiteElements" select="$suiteElements"/> <xsl:with-param name="reporterOutputElement" select="reporter-output"/> </xsl:call-template> <!--TODO: Review this--> <xsl:result-document href="{testng:absolutePath('overview- chart.svg')}" format="xml"> <svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" width="{$chartWidth}" height="{$chartHeight}" viewBox="0 0 900 300"> <defs> <style type="text/css"> <![CDATA[ .axistitle { font- weight:bold; font-size:24px; font-family:Arial; text-anchor:middle; } .xgrid, .ygrid, .legendtext { font-weight:normal; font-size:24px; font-family:Arial; } .xgrid {text- anchor:middle;} .ygrid {text-anchor:end;} .gridline { stroke:black; stroke-width:1; } .values { fill:black; stroke:none; text-anchor:middle; font-size:12px; font-weight:bold; } ]]> </style> </defs> <svg id="graphzone" preserveAspectRatio="xMidYMid meet" x="0" y="0"> <xsl:variable name="testCaseElements" select=" if (suite/@url) then if (document (suite/@url)/suite/test/@url) then document(document(suite/@url)/suite/test/@url)/test else document(suite/@url)/suite/test else suite/test"/> <xsl:variable name="failedCount" select="testng:suiteMethodsCount($testCaseElements, 'FAIL')"/> <xsl:variable name="passedCount" select="testng:suiteMethodsCount($testCaseElements, 'PASS')"/> <xsl:variable name="skippedCount" select="testng:suiteMethodsCount($testCaseElements, 'SKIP')"/> <xsl:variable name="totalCount" select="testng:suiteMethodsCount($testCaseElements, '*')"/> <xsl:variable name="pi" select="3.141592"/> <xsl:variable name="radius" select="130"/> <xsl:variable name="failedPercent" select="format-number($failedCount div $totalCount, '###%')"/> <xsl:variable name="failedAngle" select="($failedCount div $totalCount) * $pi * 2"/> <xsl:variable name="failedX" select="$radius * math:cos($failedAngle)"/> <xsl:variable name="failedY" select="-1 * $radius * math:sin($failedAngle)"/> <xsl:variable name="failedArc" select="if ($failedAngle >= $pi) then 1 else 0"/> <xsl:variable name="failedAngle_text" select="$failedAngle div 2"/> <xsl:variable name="failedX_text" select="($radius div 2) * math:cos($failedAngle_text)"/> <xsl:variable name="failedY_text" select="(-1 * ($radius div 2) * math:sin($failedAngle_text))"/> <xsl:variable name="passPercent" select="format-number($passedCount div $totalCount, '###%')"/> <xsl:variable name="passAngle" select="($passedCount div $totalCount) * $pi * 2"/> <xsl:variable name="passX" select="$radius * math:cos($passAngle)"/> <xsl:variable name="passY" select="-1 * $radius * math:sin ($passAngle)"/> <xsl:variable name="passArc" select="if ($passAngle >= $pi) then 1 else 0"/> <xsl:variable name="skipPercent" select="format-number($skippedCount div $totalCount, '###%')"/> <xsl:variable name="skipAngle" select="($skippedCount div $totalCount) * $pi * 2"/> <xsl:variable name="skipX" select="$radius * math:cos($skipAngle)"/> <xsl:variable name="skipY" select="-1 * $radius * math:sin($skipAngle)"/> <xsl:variable name="skipArc" select="if ($skipAngle >= $pi) then 1 else 0"/> <rect style="fill:red;stroke-width:1;stroke:black;" x="10" y="86" width="20" height="20"/> <text class="legendtext" x="40" y="105">Failed (<xsl:value-of select="$failedPercent"/>) </text> <rect style="fill:green;stroke-width:1;stroke:black;" x="10" y="125" width="20" height="20"/> <text class="legendtext" x="40" y="143">Passed (<xsl:value-of select="$passPercent"/>) </text> <rect style="fill:yellow;stroke-width:1;stroke:black;" x="10" y="163" width="20" height="20"/> <text class="legendtext" x="40" y="182">Skipped (<xsl:value-of select="$skipPercent"/>) </text> <g style="stroke:black;stroke-width:1" transform="translate(450,150)"> <xsl:variable name="failedRotation" select="(($skippedCount) div $totalCount) * 360"/> <xsl:if test="($failedCount div $totalCount) > 0"> <g style="fill:red" transform="rotate(- {$failedRotation}) translate({round($failedX_text div 4)}, {round($failedY_text div 4)})"> <path d="M 0 0 h {$radius} A {$radius},{$radius} 0,{$failedArc},0 {$failedX},{$failedY} z"/> </g> </xsl:if> <xsl:variable name="passRotation" select="(($failedCount + $skippedCount) div $totalCount) * 360"/> <xsl:if test="($passedCount div $totalCount) > 0"> <g style="fill:green" transform="rotate(-{$passRotation})"> <path d="M 0 0 h {$radius} A {$radius},{$radius} 0,{$passArc},0 {$passX},{$passY} z"/> </g> </xsl:if> <xsl:if test="($skippedCount div $totalCount) > 0"> <g style="fill:yellow" transform="rotate(360)"> <path d="M 0 0 h {$radius} A {$radius}, {$radius} 0,{$skipArc},0 {$skipX},{$skipY} z"/> </g> </xsl:if> </g> </svg> </svg> </xsl:result-document> <!-- Results overview file --> <xsl:result-document href="{testng:absolutePath('overview.html')}" format="xhtml"> <html xmlns="http://www.w3.org/1999/xhtml"> <xsl:call-template name="htmlHead"/> <body> <h2>Test suites overview</h2> <table width="100%"> <tr> <td align="center" id="chart-container"> <script type="text/javascript"> renderSvgEmbedTag(<xsl:value-of select="$chartWidth"/>, <xsl:value-of select="$chartHeight"/>); </script> </td> </tr> </table> <xsl:for-each select="$suiteElements"> <xsl:variable name="testCaseElements" select="if (test/@url) then document(test/@url)/test else test"/> <table width="100%" cellpadding="5" cellspacing="1"> <tr style="background-color: #eaf0f7;"> <td width="100%"> <div class="{testng:suiteStateClass($testCaseElements)}"/> <xsl:value-of select="@name"/> </td> <xsl:call-template name="percentageOverview"> <xsl:with-param name="failedCount" select="testng:suiteMethodsCount($testCaseElements, 'FAIL')"/> <xsl:with-param name="passedCount" select="testng:suiteMethodsCount ($testCaseElements, 'PASS')"/> <xsl:with-param name="skippedCount" select="testng:suiteMethodsCount($testCaseElements, 'SKIP')"/> <xsl:with-param name="totalCount" select="testng:suiteMethodsCount ($testCaseElements, '*')"/> <xsl:with-param name="totalDuration" select="testng:methodsDuration($testCaseElements/class/test-method)"/> </xsl:call-template> </tr> <xsl:for-each select="$testCaseElements"> <tr style="background-color: #f5f5f5; font-size: 12px;"> <td> <xsl:value-of select="@name"/> </td> <td align="center"> <xsl:value-of select="testng:testCaseMethodsCount(., 'FAIL')"/> </td> <td align="center"> <xsl:value-of select="testng:testCaseMethodsCount(., 'PASS')"/> </td> <td align="center"> <xsl:value-of select="testng:testCaseMethodsCount(., 'SKIP')"/> </td> <td align="center"> <xsl:value-of select="testng:testCaseMethodsCount(., '*')"/> </td> <td align="center" style="font-weight: bold;"> <xsl:value-of select="if (testng:testCaseMethodsCount(., '*') > 0) then format-number(testng:testCaseMethodsCount(., 'PASS') div testng:testCaseMethodsCount(., '*'), '###%') else '100%'"/> </td> <xsl:if test="compare($testNgXslt.showRuntimeTotals, 'true') = 0"> <td align="center" nowrap="true"> <xsl:value-of select="testng:methodsDuration(./class/test-method)"/> </td> </xsl:if> </tr> </xsl:for-each> </table> <br/> </xsl:for-each> <xsl:call- template name="powered-by"/> </body> </html> </xsl:result-document> <!-- Reporter output file --> <xsl:result-document href="{testng:absolutePath('reporterOutput.html')}" format="xhtml"> <html xmlns="http://www.w3.org/1999/xhtml"> <xsl:call-template name="htmlHead"/> <body> <h2>Reporter output</h2> <xsl:for-each select="reporter-output/line"> <div> <code> <xsl:value-of select="."/> </code> </div> </xsl:for-each> <xsl:call-template name="powered-by"/> </body> </html> </xsl:result-document> </xsl:template> <xsl:template name="navigationFile"> <xsl:param name="suiteElements"/> <xsl:param name="reporterOutputElement"/> <xsl:result-document href="{testng:absolutePath('navigation.html')}" format="xhtml"> <html xmlns="http://www.w3.org/1999/xhtml"> <xsl:call-template name="htmlHead"/> <body> <h2 style="margin-bottom: 5px;"> <xsl:value-of select="testng:getVariableSafe($testNgXslt.reportTitle, 'TestNG Results')"/> </h2> <div> <a href="overview.html" target="content" onclick="javscript:clearAllSelections();">Results overview </a> </div> <div> <a href="reporterOutput.html" target="content" onclick="javscript:clearAllSelections();">Reporter output </a> </div> <div> <xsl:for-each select="$suiteElements"> <xsl:variable name="testCaseElements" select="if (test/@url) then document(test/@url)/test else test"/> <table class="suiteMenuHeader" width="100%" cellpadding="0" cellspacing="0"> <tr> <td nowrap="true"> <b> <a href="{testng:suiteContentFileName(.)}" target="content" onclick="javscript:clearAllSelections();"> <xsl:value-of select="@name"/> </a> </b> <div style="margin: 3px 0 3px 0;"> <a href="{testng:suiteGroupsFileName(.)}" target="content" onclick="javscript:clearAllSelections();"> <xsl:value-of select="count (./groups/group)"/> Groups </a> </div> <span style="color: red;"> <xsl:value-of select="testng:suiteMethodsCount($testCaseElements, 'FAIL')"/> </span> / <span style="color: green;"> <xsl:value-of select="testng:suiteMethodsCount ($testCaseElements, 'PASS')"/> </span> / <span style="color: yellow;"> <xsl:value-of select="testng:suiteMethodsCount($testCaseElements, 'SKIP')"/> </span> / <span> <xsl:value-of select="testng:suiteMethodsCount($testCaseElements, '*')"/> </span> </td> <td style="font-weight: bold;"> <xsl:value-of select="format-number (testng:suiteMethodsCount($testCaseElements, 'PASS') div testng:suiteMethodsCount($testCaseElements, '*'), '###%')"/> </td> </tr> </table> <xsl:call-template name="suiteContentFile"> <xsl:with-param name="suiteElement" select="."/> </xsl:call-template> <xsl:call-template name="suiteGroupsFile"> <xsl:with-param name="suiteElement" select="."/> </xsl:call-template> <xsl:call-template name="suiteTestCasesLinks"> <xsl:with-param name="testCases" select="$testCaseElements"/> </xsl:call-template> <xsl:call-template name="suiteTestCasesContentFiles"> <xsl:with-param name="testCases" select="$testCaseElements"/> </xsl:call-template> </xsl:for-each> </div> </body> </html> </xsl:result-document> </xsl:template> <xsl:template name="suiteContentFile"> <xsl:param name="suiteElement"/> <xsl:variable name="testCaseElements" select="if (test/@url) then document(test/@url)/test else test"/> <xsl:result-document href="{testng:absolutePath(testng:suiteContentFileName($suiteElement))}" format="xhtml"> <html> <xsl:call-template name="htmlHead"/> <body> <table width="100%" style="font-size: 16px; margin-bottom: 10px;" cellspacing="1"> <tr> <td width="100%"> All methods in suite <b> <xsl:value-of select="./@name"/> </b> </td> <xsl:call-template name="percentageOverview"> <xsl:with-param name="failedCount" select="testng:suiteMethodsCount($testCaseElements, 'FAIL')"/> <xsl:with-param name="passedCount" select="testng:suiteMethodsCount ($testCaseElements, 'PASS')"/> <xsl:with-param name="skippedCount" select="testng:suiteMethodsCount($testCaseElements, 'SKIP')"/> <xsl:with-param name="totalCount" select="testng:suiteMethodsCount ($testCaseElements, '*')"/> <xsl:with-param name="totalDuration" select="testng:methodsDuration($testCaseElements/class/test-method)"/> </xsl:call-template> </tr> </table> <xsl:call-template name="testMethods"> <xsl:with-param name="classes" select="$testCaseElements/class"/> <xsl:with-param name="failedMethods" select="$testCaseElements/class/test-method[@status='FAIL']"/> <xsl:with-param name="passedMethods" select="$testCaseElements/class/test-method[@status='PASS']"/> <xsl:with-param name="skipedMethods" select="$testCaseElements/class/test-method[@status='SKIP']"/> </xsl:call-template> <xsl:call-template name="powered-by"/> </body> </html> </xsl:result-document> </xsl:template> <xsl:template name="suiteGroupsFile"> <xsl:param name="suiteElement"/> <xsl:result-document href="{testng:absolutePath(testng:suiteGroupsFileName($suiteElement))}" format="xhtml"> <html xmlns="http://www.w3.org/1999/xhtml"> <xsl:call-template name="htmlHead"/> <body> <h2> Groups for suite: <b> <xsl:value-of select="$suiteElement/@name"/> </b> </h2> <xsl:for-each select="$suiteElement/groups/group"> <xsl:sort order="ascending" select="@name"/> <table style="margin-bottom: 20px; font-size: 12px; width:100%;" cellpadding="3" cellspacing="1"> <tr> <td style="background-color: #f5f5f5;"> <div style="font-size: 18px;"> <xsl:value-of select="./@name"/> </div> </td> </tr> <xsl:for-each select="method"> <tr> <td style="background-color: #eaf0f7;"> <xsl:value-of select="@signature"/> </td> </tr> </xsl:for-each> </table> </xsl:for-each> <xsl:call-template name="powered-by"/> </body> </html> </xsl:result-document> </xsl:template> <xsl:template name="testMethods"> <xsl:param name="classes"/> <xsl:param name="failedMethods"/> <xsl:param name="passedMethods"/> <xsl:param name="skipedMethods"/> <xsl:param name="filePrefix"/> <div style="width: 200px;"> <label for="groupMethodsCheckBox" style="font-weight: bold; margin: 0;"> <input id="groupMethodsCheckBox" type="checkbox" onclick="switchTestMethodsView(this)"> <xsl:if test="testng:isFilterSelected('BY_CLASS') = 'true'"> <xsl:attribute name="checked" select="true"/> </xsl:if> </input> Group by class </label> <br/> <label for="methodsFilter_ALL" style="font-weight: bold; margin: 0;"> <input id="methodsFilter_ALL" type="checkbox" onclick="testMethodsFilterChanged(this, 'ALL')"> <xsl:if test="testng:isFilterSelected('FAIL') = 'true' and testng:isFilterSelected('PASS') = 'true' and testng:isFilterSelected ('SKIP') = 'true' and testng:isFilterSelected('CONF') = 'true'"> <xsl:attribute name="checked" select="true"/> </xsl:if> </input> All </label> </div> <label for="methodsFilter_FAIL" style="margin-left: 20px;"> <input id="methodsFilter_FAIL" type="checkbox" onclick="testMethodsFilterChanged(this, 'FAIL')"> <xsl:if test="testng:isFilterSelected('FAIL') = 'true'"> <xsl:attribute name="checked" select="true"/> </xsl:if> </input> Failed </label> <label for="methodsFilter_PASS"> <input id="methodsFilter_PASS" type="checkbox" onclick="testMethodsFilterChanged(this, 'PASS')"> <xsl:if test="testng:isFilterSelected('PASS') = 'true'"> <xsl:attribute name="checked" select="true"/> </xsl:if> </input> Passed </label> <label for="methodsFilter_SKIP"> <input id="methodsFilter_SKIP" type="checkbox" onclick="testMethodsFilterChanged(this, 'SKIP')"> <xsl:if test="testng:isFilterSelected('SKIP') = 'true'"> <xsl:attribute name="checked" select="true"/> </xsl:if> </input> Skipped </label> <label for="methodsFilter_CONF"> <input id="methodsFilter_CONF" type="checkbox" onclick="testMethodsFilterChanged(this, 'CONF')"> <xsl:if test="testng:isFilterSelected('CONF') = 'true'"> <xsl:attribute name="checked" select="true"/> </xsl:if> </input> Config </label> <br/> <!-- Display methods list grouped by status --> <div id="testMethodsByStatus"> <xsl:if test="testng:isFilterSelected('BY_CLASS') = 'true'"> <xsl:attribute name="style" select="'display: none;'"/> </xsl:if> <table class="testMethodsTable" cellpadding="0" cellspacing="0"> <tr class="methodsTableHeader"> <td width="100%">Name</td> <td nowrap="true">Started</td> <td nowrap="true">Duration</td> <td>Exception</td> </tr> <xsl:call-template name="testMethodsList"> <xsl:with-param name="methodList" select="$failedMethods"/> <xsl:with-param name="category" select="'byStatus_failed'"/> </xsl:call-template> <xsl:call-template name="testMethodsList"> <xsl:with-param name="methodList" select="$passedMethods"/> <xsl:with-param name="category" select="'byStatus_passed'"/> </xsl:call-template> <xsl:call-template name="testMethodsList"> <xsl:with-param name="methodList" select="$skipedMethods"/> <xsl:with-param name="category" select="'byStatus_skiped'"/> </xsl:call-template> </table> </div> <!-- Display methods list grouped by class --> <div id="testMethodsByClass"> <xsl:if test="testng:isFilterSelected('BY_CLASS') != 'true'"> <xsl:attribute name="style" select="'display: none;'"/> </xsl:if> <xsl:for-each select="$classes"> <xsl:sort order="ascending" select="@name"/> <table class="testMethodsTable" cellpadding="0" cellspacing="0"> <tr> <td colspan="4"> <h3 style="display: inline;"> <xsl:value-of select="./@name"/> </h3> </td> </tr> <tr class="methodsTableHeader"> <td width="100%">Name</td> <td nowrap="true">Started</td> <td nowrap="true">Duration</td> <td>Exception</td> </tr> <xsl:call-template name="testMethodsList"> <!--<xsl:with-param name="methodList" select="./test-method[not(@is-config)]"/>--> <xsl:with- param name="methodList" select="./test-method"/> <xsl:with-param name="category" select="'byClass'"/> <xsl:with-param name="sortByStartTime" select="'true'"/> </xsl:call-template> </table> <br/> </xsl:for-each> </div> </xsl:template> <xsl:template name="testMethodsList"> <xsl:param name="methodList"/> <xsl:param name="category"/> <xsl:param name="sortByStartTime"/> <xsl:for-each select="$methodList"> <xsl:sort order="ascending" select="if (compare($sortByStartTime, 'true') = 0) then @started-at else ''"/> <xsl:variable name="methodId" select="concat(../@name, '_', @name, '_', $category, '_', @status, position())"/> <xsl:variable name="detailsId" select="concat($methodId, '_details')"/> <xsl:variable name="exceptionDetailsId" select="concat($methodId, '_exception')"/> <tr id="{concat($methodId, '_row')}" class="{testng:testMethodStatus (.)}"> <xsl:if test="testng:isFilterSelected(@status) != 'true'"> <!--<xsl:attribute name="style" select="'display: none;'"/>--> </xsl:if> <td width="100%" class="firstMethodCell"> <a onclick="toggleDetailsVisibility('{$detailsId}')"> <xsl:value-of select="concat(@name, '(', testng:trim(testng:concatParams(./params/param)), ')')"/> </a> </td> <td nowrap="true"> <xsl:value-of select="substring(@started-at, 12, 8)"/> </td> <td nowrap="true" align="right"> <xsl:value-of select="testng:formatDuration(@duration-ms)"/> </td> <td nowrap="true"> <xsl:if test="./exception"> <a onclick="toggleDetailsVisibility('{$exceptionDetailsId}')"> <xsl:value-of select="concat(exception/@class, ': ', exception/message)"/> </a> </xsl:if>   </td> </tr> <tr> <td colspan="4" style="padding: 0; background-color: white; border-style: none; height: 0px;"> <div id="{$detailsId}" class="testMethodDetails"> <xsl:call-template name="formField"> <xsl:with-param name="label" select="'Name'"/> <xsl:with-param name="value" select="@name"/> </xsl:call-template> <xsl:call-template name="formField"> <xsl:with-param name="label" select="'Description'"/> <xsl:with-param name="value" select="@description"/> </xsl:call-template> <xsl:call-template name="formField"> <xsl:with-param name="label" select="'Signature'"/> <xsl:with-param name="value" select="@signature"/> </xsl:call-template> <xsl:if test="./params"> <xsl:call-template name="formField"> <xsl:with-param name="label" select="'Parameters'"/> <xsl:with-param name="value" select="testng:concatParams(./params/param)"/> </xsl:call- template> </xsl:if> <xsl:call-template name="formField"> <xsl:with-param name="label" select="'Start time'"/> <xsl:with-param name="value" select="substring(@started-at, 12, 8)"/> </xsl:call-template> <xsl:call- template name="formField"> <xsl:with-param name="label" select="'End time'"/> <xsl:with-param name="value" select="substring(@finished-at, 12, 8)"/> </xsl:call-template> <xsl:call-template name="formField"> <xsl:with-param name="label" select="'Duration'"/> <xsl:with-param name="value" select="testng:formatDuration(@duration- ms)"/> </xsl:call-template> <xsl:call-template name="formField"> <xsl:with-param name="label" select="'In groups:'"/> <xsl:with-param name="value" select="@groups"/> </xsl:call-template> <xsl:if test="@depends-on-methods"> <xsl:call-template name="formFieldList"> <xsl:with-param name="label" select="'Depends on methods'"/> <xsl:with-param name="value" select="tokenize(@depends-on-methods, ',')"/> </xsl:call-template> </xsl:if> <xsl:if test="@depends-on-groups"> <xsl:call-template name="formFieldList"> <xsl:with-param name="label" select="'Depends on groups'"/> <xsl:with-param name="value" select="tokenize(@depends-on-groups, ',')"/> </xsl:call-template> </xsl:if> </div> </td> </tr> <tr> <xsl:if test="exception"> <td colspan="4" style="padding: 0; background-color: white; border-style: none; height: 0px;"> <div id="{$exceptionDetailsId}" class="testMethodDetails"> <xsl:choose> <xsl:when test="exception/full-stacktrace"> <pre style="padding: 5px; margin: 0;"> <xsl:value-of select="testng:trim (exception/full-stacktrace)"/> </pre> </xsl:when> <xsl:when test="exception/short-stacktrace and not (exception/full-stacktrace)"> <pre style="padding: 5px; margin: 0;"> <xsl:value-of select="testng:trim(exception/short-stacktrace)"/> </pre> </xsl:when> <xsl:otherwise> <pre style="padding: 5px; margin: 0;"><No stacktrace information></pre> </xsl:otherwise> </xsl:choose> </div> </td> </xsl:if> </tr> </xsl:for-each> </xsl:template> <xsl:template name="suiteTestCasesLinks"> <xsl:param name="testCases"/> <xsl:for-each select="$testCases"> <xsl:sort order="ascending" select="if (compare ($testNgXslt.sortTestCaseLinks, 'true') = 0) then @name else ''"/> <div class="testCaseLink" onclick="javscript:selectTestCaseLink(this); parent.content.location='{testng:testCaseContentFileName(.)}'"> <div class="{if (count(./class/test-method[@status='FAIL']) > 0) then 'testCaseFail' else if ((count(./class/test-method[@status='FAIL']) = 0) and (count(./class/test-method [@status='PASS']) > 0)) then 'testCasePass' else 'testCaseSkip'}"> </div> <xsl:value-of select="@name"/> </div> </xsl:for- each> </xsl:template> <xsl:template name="suiteTestCasesContentFiles"> <xsl:param name="testCases"/> <xsl:for-each select="$testCases"> <xsl:result-document href="{testng:absolutePath (testng:testCaseContentFileName(.))}" format="xhtml"> <html> <xsl:call-template name="htmlHead"/> <body> <table width="100%" style="font-size: 16px; margin- bottom: 10px;" cellspacing="1"> <tr> <td width="100%"> Test case <b> <xsl:value-of select="./@name"/> </b> </td> <xsl:call-template name="percentageOverview"> <xsl:with-param name="failedCount" select="testng:testCaseMethodsCount(., 'FAIL')"/> <xsl:with-param name="passedCount" select="testng:testCaseMethodsCount(., 'PASS')"/> <xsl:with-param name="skippedCount" select="testng:testCaseMethodsCount(., 'SKIP')"/> <xsl:with-param name="totalCount" select="testng:testCaseMethodsCount(., '*')"/> <xsl:with-param name="totalDuration" select="testng:methodsDuration(./class/test-method)"/> </xsl:call-template> </tr> </table> <xsl:call-template name="testMethods"> <xsl:with-param name="classes" select="./class"/> <xsl:with-param name="failedMethods" select="./class/test-method[@status='FAIL']"/> <xsl:with-param name="passedMethods" select="./class/test-method[@status='PASS']"/> <xsl:with-param name="skipedMethods" select="./class/test-method[@status='SKIP']"/> </xsl:call-template> <xsl:call-template name="powered-by"/> </body> </html> </xsl:result-document> </xsl:for-each> </xsl:template> <xsl:template name="percentageOverview"> <xsl:param name="failedCount"/> <xsl:param name="passedCount"/> <xsl:param name="skippedCount"/> <xsl:param name="totalCount"/> <xsl:param name="totalDuration"/> <td style="background-color: #FFBBBB; padding: 3px 3px 3px 0;" align="center"> <div style="width: 50px;"> <xsl:value-of select="$failedCount"/> </div> </td> <td style="background-color: lightgreen; padding: 3px 3px 3px 0;" align="center"> <div style="width: 50px;"> <xsl:value-of select="$passedCount"/> </div> </td> <td style="background-color: #FFFFBB; padding: 3px 3px 3px 0;" align="center"> <div style="width: 50px;"> <xsl:value-of select="$skippedCount"/> </div> </td> <td align="center" style="background-color: #eaf0f7; padding: 3px 3px 3px 0;"> <div style="width: 50px;"> <xsl:value-of select="$totalCount"/> </div> </td> <td align="center" style="font-weight: bold; background-color: #eaf0f7; padding: 3px 3px 3px 0;"> <div style="width: 50px;"> <xsl:value-of select="if ($totalCount > 0) then format-number($passedCount div $totalCount, '###%') else '100%'"/> </div> </td> <xsl:if test="compare($testNgXslt.showRuntimeTotals, 'true') = 0"> <td style="background-color: #eaf0f7; padding: 3px 3px 3px 0;" align="center" nowrap="true"> <xsl:value-of select="$totalDuration"/> </td> </xsl:if> </xsl:template> <xsl:template name="powered-by"> <div style="margin-top: 15px; color: gray; text-align: center; font-size: 9px;"> Generated with <a href="http://code.google.com/p/testng-xslt/" style="color: #8888aa;" target="_blank"> TestNG XSLT </a> </div> </xsl:template> </xsl:stylesheet>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值