Chapter3: 将TestStand的XML结果转换成Junit格式
本系列文章见总链接:
总章:TestStand+Jenkins+Testlink 自动化测试平台搭建
参照TestStand提供的文档https://forums.ni.com/t5/Example-Code/Converting-TestStand-XML-Reports-to-JUnit/ta-p/3689131?profile.language=zh-CN
可以将TestStand生成的XML log文件转换成Testlink插件需要的Junit格式。
下载msxsl.exe文件
下载地址:https://www.microsoft.com/en-us/download/details.aspx?id=21714
修改XML_Junit_Simple.xsl文件
下载地址:https://forums.ni.com/ni/attachments/ni/3039/8416/1/XML_JUnit_Simple.xsl
修改XML_Junit_Simple.xsl文件
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ts="http://www.ni.com/TestStand/16.0.0/PropertyObjectFile" exclude-result-prefixes="ts"> <xsl:strip-space elements="*"/> <xsl:output method="xml" encoding="UTF-8" indent="yes"/> <!--创建变量,获取测试日志中记录的脚本名,脚本名是.seq后缀的文件--> <xsl:variable name="FileName"><xsl:value-of select="Reports/Report/Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='SequenceCall']/Prop[@Name='SequenceFile']/Value"/></xsl:variable> <xsl:variable name="ScriptFileName" select="substring-after($FileName,'Test Case\')"/> <xsl:variable name="ScriptName" select="substring-before($ScriptFileName,'.seq')"/> <!--创建TestSuite标签,包含name,tests,time等属性--> <xsl:template match="Reports/Report"> <testsuite> <xsl:attribute name="name">TestSuite</xsl:attribute> <xsl:attribute name="tests"> <xsl:value-of select="@StepCount"/> </xsl:attribute> <xsl:attribute name="hostname"> <xsl:value-of select="Prop[@Name='StationInfo']/Prop[@Name='StationID']/Value"/> </xsl:attribute> <xsl:attribute name="time"> <xsl:value-of select="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='TotalTime']/Value"/> </xsl:attribute> <!--获取整个TestSuite的测试结果--> <properties> <property name="UUT Result" > <xsl:attribute name="value"> <xsl:value-of select="@UUTResult"/> </xsl:attribute> </property> </properties> <xsl:apply-templates select="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='SequenceCall']/Prop[@Name='ResultList']"/> </testsuite> </xsl:template> <xsl:template match="Prop[@Name='ResultList']"> <xsl:for-each select="Value"> <xsl:choose> <!--忽略条件语句和循环语句等无效的测试结果--> <xsl:when test="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepType']/Value = 'NI_Flow_If'"> </xsl:when> <xsl:when test="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepType']/Value = 'NI_Flow_ElseIf'"> </xsl:when> <xsl:when test="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepType']/Value = 'NI_Flow_Else'"> </xsl:when> <xsl:when test="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepType']/Value = 'NI_Flow_End'"> </xsl:when> <xsl:when test="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepType']/Value = 'NI_Flow_For'"> </xsl:when> <xsl:when test="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepType']/Value = 'NI_Flow_While'"> </xsl:when> <xsl:when test="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepType']/Value = 'NI_Flow_DoWhile'"> </xsl:when> <xsl:otherwise> <testcase> <!--依据Junit测试生成的XML格式,定义TestCase的Classname,结合在Testlink中Custom Field中的值,我们定义为"文件名.1Main"等--> <xsl:if test="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepGroup']/Value= 'Setup'"> <xsl:attribute name="classname"><xsl:copy-of select="$ScriptName" />.0<xsl:value-of select="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepGroup']/Value"/></xsl:attribute> </xsl:if> <xsl:if test="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepGroup']/Value= 'Main'"> <xsl:attribute name="classname"><xsl:copy-of select="$ScriptName" />.1<xsl:value-of select="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepGroup']/Value"/></xsl:attribute> </xsl:if> <xsl:if test="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepGroup']/Value= 'Cleanup'"> <xsl:attribute name="classname"><xsl:copy-of select="$ScriptName" />.2<xsl:value-of select="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepGroup']/Value"/></xsl:attribute> </xsl:if> <!--将Teststand脚本的每一步的名称取做Name值,同时为了在Jenkins的JUnit Report结果中能正确显示步骤顺序,我们定义为"ID000000_Step0000_步骤名"--> <xsl:attribute name="name">ID<xsl:value-of select="format-number(Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='Id']/Value,'000000')"/>_Step<xsl:value-of select="format-number(Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='Index']/Value,'0000')"/>_<xsl:value-of select="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepName']/Value"/></xsl:attribute> <!--定义TestCase的status,time等属性--> <xsl:attribute name="status"> <xsl:value-of select="Prop[@Type='TEResult']/Prop[@Name='Status']/Value"/> </xsl:attribute> <xsl:attribute name="time"> <xsl:value-of select="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='TotalTime']/Value"/> </xsl:attribute> <xsl:choose> <!--若测试步骤结果跳过,失败或错误,则需要多增加一个子标签,以便Testlink插件识别并标记--> <xsl:when test="Prop[@Type='TEResult']/Prop[@Name='Status']/Value = 'Skipped'"> <skipped/> </xsl:when> <xsl:when test="Prop[@Type='TEResult']/Prop[@Name='Status']/Value = 'Failed'"> <failure/> </xsl:when> <xsl:when test="Prop[@Type='TEResult']/Prop[@Name='Status']/Value = 'Error'"> <error> <xsl:attribute name="message"> <xsl:value-of select="normalize-space(Prop[@Type='TEResult']/Prop[@Name='Error']/Prop[@Name='Msg']/Value)"/> </xsl:attribute> </error> </xsl:when> </xsl:choose> </testcase> </xsl:otherwise> </xsl:choose> <!--若只获取TestStand MainSequence的测试结果,就注销这段代码。若要获取所有子Sequence的结果,则取消下段注释--> <!--<xsl:if test="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='StepType']/Value = 'SequenceCall'"> <xsl:apply-templates select="Prop[@Type='TEResult']/Prop[@Name='TS']/Prop[@Name='SequenceCall']/Prop[@Name='ResultList']"/> </xsl:if> --> </xsl:for-each> </xsl:template> </xsl:stylesheet>
查看生成的Report_JUnit.xml文件,内容被删减了一部分
<?xml version="1.0" encoding="UTF-8"?> <testsuite name="TestSuite" tests="1179" hostname="M5255233" time="98.4792893"> <properties> <property name="UUT Result" value="Passed" /> </properties> <testcase classname="TestWithTestlink.0Setup" name="ID000003_Step0000_Prepare Auto Test Environment" status="Passed" time="1.106301" /> <testcase classname="TestWithTestlink.0Setup" name="ID000102_Step0001_Power off and on" status="Passed" time="29.7245942" /> <testcase classname="TestWithTestlink.1Main" name="ID000205_Step0000_Set Unit Type" status="Passed" time="9.8879755" /> <testcase classname="TestWithTestlink.1Main" name="ID000316_Step0001_Get the value of the Variable" status="Done" time="0.0010559" /> <testcase classname="TestWithTestlink.1Main" name="ID000317_Step0002_Get Index of Point" status="Passed" time="0.009622" /> <testcase classname="TestWithTestlink.1Main" name="ID000318_Step0003_Get the value of PublicORBritishSystem" status="Passed" time="0.2046701" /> </testsuite>
备忘:
将数值前面加0,凑成固定位数的数值
<xsl:value-of select="format-number(msg:BankAccount/msg:Counter, '000000000000000')" />
定义全局变量,并使用,参照https://www.w3school.com.cn/xsl/el_variable.asp
<xsl:variable name="color" select="'red'" /> <xsl:copy-of select="$header" />
关于Junit XML样本,参照https://llg.cubic.org/docs/junit/,其中定义了XML应该包含哪些标签,哪些属性,用来记录哪些信息。
.
<xsl:value-ofselect="format-number(msg:BankAccount/msg:Counter, '000000000000000')"/>