使用Python把Gtest XML测试结果转换为HTML格式
在最近的测试中,使用gtest测试框架对c语言代码进行测试,结果以XML文件来保存,但是测试结果的查阅和分析非常不方便。便想着把xml的结果直接转为HTML文件,方便和Jenkins系统对接显示。因现在的测试方法是使用Python脚本来控制gtest的测试文件运行的,故选用Python脚本来实现xml转html的功能。
- 先看结果:
个人对于html不是很熟悉,只是简单的了解各个元素。要求只有一个,生成的结果清晰明了,便于查阅即可。
- 环境准备:
安装libxml2 libxstl模块
Python 2.7环境
Ubuntu 14.04 验证下通过。
- 输出:
执行结果生成同名的html文件。
Python代码如下此段代码是在网上搜索参考的:
原文地址如下:http://blog.csdn.net/zhaoweikid/article/details/74837
我这里进行了简单的修改,增加了命令行参数。
#!/usr/bin/python
#coding=utf8 import sys
import libxml2
import libxslt class compoundXML:
def __init__(self):
self._result=None
self._xsl=None
self._xml=None def do(self,xml_file_name,xsl_file_name='gtest.xsl'):
self._xml = libxml2.parseFile(xml_file_name)
if self._xml ==None:
return 0
styledoc = libxml2.parseFile(xsl_file_name)
if styledoc == None:
return 0
self._xsl = libxslt.parseStylesheetDoc(styledoc)
if self._xsl == None:
return 0
self._result = self._xsl.applyStylesheet(self._xml, None)
def get_xml_doc(self):
return self._result def get_translated(self):
return self._result.serialize('UTF-8') def save_translated(self, file_name):
self._xsl.saveResultToFilename(file_name, self._result, 0) def release(self):
'''
this function must be called in the end.
'''
self._xsl.freeStylesheet()
self._xml.freeDoc()
self._result.freeDoc()
self._xsl = None
self._xml = None
self._result = None def xml2html(xml_file):
test=compoundXML()
test.do(xml_file)
test.save_translated(xml_file+'.html')
test.release() if __name__ =='__main__':
filename=sys.argv[1];
test=compoundXML()
test.do(filename)
#print test.get_translated()
test.save_translated(filename+'.html')
test.release()
但是这个原文链接讲的非常不详细,只是把Python脚本写了,没有放xsl模板,在尝试的时候尝试了好久,才明白过来需要一个xsl模板,在使用xsl模板来解析gtest测试结果的过程中,调试了好久,终于有一个让自己满意的显示结果。
Xslt解析xml生成html文件,是按照xsl文件的模板来解析,这些都是教训哈,摸索了好久。
关键是根据gtest的xml文件格式,编写一个合适的xsl模板。
解析gtest xml的Xsl模板如下:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> <xsl:output method="html" indent="yes"/> <xsl:template match="/"> <table cellpadding="2" cellspacing="5" border="1px">
<tr>
<th bgcolor="#808080"><font color="#FFFFFF">Testcase Num</font></th>
<th bgcolor="#808080"><font color="#FFFFFF">Failure Num</font></th>
</tr>
<tr>
<td style="font-family: Verdana; font-size: 15px; font-weight: bold;"><xsl:value-of select="testsuites/@tests"/> </td>
<td style="font-family: Verdana; font-size: 15px; font-weight: bold;"><xsl:value-of select="testsuites/@failures"/> </td>
</tr>
</table> <table cellpadding="2" cellspacing="5">
<tr><td style="font-family: Verdana; font-size: 10px;"> <table align="left" cellpadding="2" cellspacing="0" style="font-family: Verdana; font-size: 10px;">
<tr>
<th bgcolor="#808080"><font color="#FFFFFF"><b>TestSuites</b></font></th>
<th bgcolor="#808080">
<table width="1000px" align="left" cellpadding="1" cellspacing="0" style="font-family: Verdana; font-size: 10px;">
<tr style="font-family: Verdana; font-size: 10px;">
<td width="15%"><font color="#FFFFFF"><b>Testcase</b></font></td>
<td width="25%"><font color="#FFFFFF"><b>Result</b></font></td>
<td width="75%"><font color="#FFFFFF"><b>ErrorInfo</b></font></td>
</tr>
</table>
</th>
</tr>
<xsl:for-each select="testsuites/testsuite">
<tr>
<td style="border: 1px solid #808080"><xsl:value-of select="@name"/></td>
<td style="border: 1px solid #808080">
<table width="1000px" align="left" cellpadding="1" cellspacing="0" style="font-family: Verdana; font-size: 10px;">
<xsl:for-each select="testcase">
<tr>
<td style="border: 1px solid #808080" width="15%" rowspan="@tests"><xsl:value-of select="@name"/></td>
<xsl:choose>
<xsl:when test="failure">
<td style="border: 1px solid #808080" bgcolor="#ff00ff" width="25%">Failure</td>
<td style="border: 1px solid #808080" bgcolor="#ff00ff" width="70%"><xsl:value-of select="failure/@message"/></td>
</xsl:when>
<xsl:otherwise>
<td style="border: 1px solid #808080" width="25%">Success</td>
<td style="border: 1px solid #808080" width="70%"><xsl:value-of select="failure/@message"/></td>
</xsl:otherwise>
</xsl:choose>
</tr>
</xsl:for-each>
</table>
</td>
</tr>
</xsl:for-each>
</table>
</td>
</tr>
</table> </xsl:template>
</xsl:stylesheet>
Xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="22" failures="3" disabled="0" errors="0" time="73.802" name="AllTests">
<testsuite name="TEST_CStart" tests="14" failures="0" disabled="0" errors="0" time="35.012">
<testcase name="Normal_ORAY" status="run" time="5.001" classname="TEST_CStart" />
<testcase name="WithInited_ORAY" status="run" time="0" classname="TEST_CStart" />
<testcase name="Normal_NOIP" status="run" time="5.001" classname="TEST_CStart" />
<testcase name="WithInited_NOIP" status="run" time="0.001" classname="TEST_CStart" />
<testcase name="Normal_HIVIEW" status="run" time="5.001" classname="TEST_CStart" />
<testcase name="WithInited_HIVIEW" status="run" time="0" classname="TEST_CStart" />
<testcase name="Normal_CHANGEIP" status="run" time="5.001" classname="TEST_CStart" />
<testcase name="WithInited_CHANGEIP" status="run" time="0.001" classname="TEST_CStart" />
<testcase name="Normal_3322" status="run" time="5.001" classname="TEST_CStart" />
<testcase name="WithInited_3322" status="run" time="0" classname="TEST_CStart" />
<testcase name="Normal_Dyndns" status="run" time="5.001" classname="TEST_CStart" />
<testcase name="WithInited_Dyndns" status="run" time="0" classname="TEST_CStart" />
<testcase name="Normal_easy" status="run" time="5.001" classname="TEST_CStart" />
<testcase name="WithInited_easy" status="run" time="0.001" classname="TEST_CStart" />
</testsuite>
<testsuite name="TEST_CStop" tests="2" failures="0" disabled="0" errors="0" time="0">
<testcase name="Normal" status="run" time="0" classname="TEST_CStop" />
<testcase name="WithoutInited" status="run" time="0" classname="TEST_CStop" />
</testsuite>
<testsuite name="TEST_DynipCInit" tests="1" failures="0" disabled="0" errors="0" time="0.001">
<testcase name="Normal_DYNIP" status="run" time="0" classname="TEST_DynipCInit" />
</testsuite>
<testsuite name="TEST_DynipCLogSet" tests="1" failures="0" disabled="0" errors="0" time="0">
<testcase name="Normal_DYNIP" status="run" time="0" classname="TEST_DynipCLogSet" />
</testsuite>
<testsuite name="TEST_DynipCRegist" tests="1" failures="1" disabled="0" errors="0" time="19.998">
<testcase name="Normal_DYNIP" status="run" time="19.998" classname="TEST_DynipCRegist">
<failure message="Value of: DynipCRegist(&ptDynipCRInfo,dwDnsAddr) Actual: 4105 Expected: 0x1004 Which is: 4100" type=""><![CDATA[../_gtest.c:400
Value of: DynipCRegist(&ptDynipCRInfo,dwDnsAddr)
Actual: 4105
Expected: 0x1004
Which is: 4100]]></failure>
</testcase>
</testsuite>
<testsuite name="TEST_DynipCRefresh" tests="1" failures="1" disabled="0" errors="0" time="3.795">
<testcase name="Normal_DYNIP" status="run" time="3.795" classname="TEST_DynipCRefresh">
<failure message="Value of: DynipCRefresh(&ptDynipCRInfo,dwDnsAddr) Actual: 4117 Expected: 0x1014 Which is: 4116" type=""><![CDATA[../_gtest.c:413
Value of: DynipCRefresh(&ptDynipCRInfo,dwDnsAddr)
Actual: 4117
Expected: 0x1014
Which is: 4116]]></failure>
</testcase>
</testsuite>
<testsuite name="TEST_DynipCDeleteRegist" tests="1" failures="1" disabled="0" errors="0" time="14.994">
<testcase name="Normal_DYNIP" status="run" time="14.994" classname="TEST_DynipCDeleteRegist">
<failure message="Value of: DynipCDeleteRegist(htonl(638699), htonl(3372250290UL),inet_addr("8.8.8.8")) Actual: 4105 Expected: 0x1000 Which is: 4096" type=""><![CDATA[../_gtest.c:425
Value of: DynipCDeleteRegist(htonl(638699), htonl(3372250290UL),inet_addr("8.8.8.8"))
Actual: 4105
Expected: 0x1000
Which is: 4096]]></failure>
</testcase>
</testsuite>
<testsuite name="TEST_CGetVersion" tests="1" failures="0" disabled="0" errors="0" time="0">
<testcase name="Normal" status="run" time="0" classname="TEST_CGetVersion" />
</testsuite>
</testsuites>
使用方法:
把Python脚本和gtest.xsl模板放在同一个目录下。
一个是使用命令行:
./xml2html.py gtest_reult.xml
二是作为函数调用:
使用xml2html(xml_file)函数进行转换。
使用Python把Gtest XML测试结果转换为HTML格式的更多相关文章
- python接口之request测试:以json格式发送post请求,.json方法,查看响应结果的情况
json和dict python中的dict类型要转换为json格式的数据需要用到json库: import json <json> = json.dumps(<dict>) ...
- 【Python爬虫实战--2】时间戳转换为指定格式日期
摘自:http://www.2cto.com/kf/201406/311477.html (1)方法: 方法一: 利用localtime()转换为时间数组,然后格式化为需要的格式,如 timeStam ...
- Anakia 转换xml文档为其他格式
一.简介 Anakia 使用JDOM 和Velocity将XML文档转换为特定格式的文档 二.解析xml文档方法 1.DOM java jdk,xml-api.jar 需要加载整个xml文档来构建层次 ...
- python专题-读取xml文件
关于python读取xml文章很多,但大多文章都是贴一个xml文件,然后再贴个处理文件的代码.这样并不利于初学者的学习,希望这篇文章可以更通俗易懂的教如何使用python 来读取xml 文件. 什么是 ...
- 用 Python 写 Robot Framework 测试
Robot Framework 框架是基于 Python 语言开发的,所以,它本质上是 Python 的一个库. 1.你懂 Python 语言. 2.又想使用 Robot Framework 测试框架 ...
- 用 ElementTree 在 Python 中解析 XML
用 ElementTree 在 Python 中解析 XML 原文: http://eli.thegreenplace.net/2012/03/15/processing-xml-in-python- ...
- 使用python+pychram进行API测试(接口测试)初级STEP 1
花了一天时间安装了解了下最基本的python+pychram进行API测试,下面这个可以指导自己以后入门:基本的开发级别还需要学习 1.python下载地址:https://www.python.or ...
- python标准库xml.etree.ElementTree的bug
使用python生成或者解析xml的方法用的最多的可能就数python标准库xml.etree.ElementTree和lxml了,在某些环境下使用xml.etree.ElementTree更方便一些 ...
- 在python中处理XML
XML是实现不同语言或程序之间进行数据交换的协议,XML文件格式如下: <data> <country name="Liechtenstein"> < ...
随机推荐
- HNOI2004 宠物收养所 解题报告
首先读完这题第一印象,是个裸题,很高兴.其次在打完代码之后,第二印象,很恶心,Treap的代码太长了,我今天下午敲了三遍,手都麻了. 废话不多说,正题.其实这个题不难,有几个点是很好的,首先,他的a值 ...
- mysql用root用户启动后其他用户无法启动不问题
问题描述:用root账户启动mysql后,在用mysql用户或其他非root账户启动不了mysql问题解决:通过看mysql的err日志,发现 Failed to open log (robert-b ...
- MYSQL分页存储过程及事务处理--转自peace
MYSQL的分页过程,和事务处理的一个测试过程. /* --名称:MYSQL版查询分页存储过程 by peace 2013-8-14 --输入参数:@fields -- 要查询的字段用逗号隔开 --输 ...
- Struts2注解学习1
这是开博的第一篇,我希望每天把我学到的东西记录下来,成为一个知识库,方便以后的学习和分享 在项目中看到用struts2注解来做,很方便,做了一个用户登录的例子 1.加载所需jar包 commons-f ...
- png压缩工具-PngoutWin
PngoutWin是一款聪明的png图片压缩工具,别的压缩工具压缩PNG是通过丢弃透明层来达到减肥的目的.可是不能透明的PNG还能叫PNG吗?PngoutWin它不会丢弃原本的透明,而是通 ...
- Yii 2.0安装
通过 Composer 安装 注意: php版本最好在5.5以上! 1.下载 Yii2的高级应用程序模板 ,然后将其解压缩到一个Web可访问的文件夹. 2.下载Composer-Setup.exe , ...
- java学习:AWT组件和事件处理的笔记(1)--菜单条,菜单,菜单项
菜单放在菜单条里,菜单项放在菜单里1.MenuBar 在java.awt包中,负责创建菜单条,即MenuBar的一个实例,便是一个菜单条. 在Frame类中的setMenuBar(Menu ...
- UVa230 Borrowers (STL)
Borrowers I mean your borrowers of books - those mutilators of collections, spoilers of the symmet ...
- 利用Azure backup备份和恢复Azure虚拟机(1)
中国区Azure最近发布了关于使用Azure Backup来备份VM服务,于3月1日正式上线,该功能对于需要对关键工作负载进行备份的用户来讲,极大的降低了操作复杂度.以前我们所使用Powershell ...
- QT VS配置UNICODE问题
默认情况下,使用VSQT插件 导入.pro后,会自动在项目文件里面预定义好宏UNICODE,可以把该宏去掉,以免造成其他程序,使用多字节的代码出错 去除的两个方法 1.打开Propject->P ...