python 生成html测试报表三步曲

<p>最近把测试框架优化了一下,原本生成的报表时txt格式的,现在搞成html格式。主要步骤如下</p>
<p><strong>首先找个html处理工具,这样处理html会简单很多</strong></p>
<p>我网上找了一下发现phy停好用,在这里非常感谢pyh的作者</p>
<p>phy源码如下</p>
<p># @file: pyh.py<br># @purpose: a HTML tag generator<br># @author: Emmanuel Turlay <<a href="mailto:turlay@cern.ch">turlay@cern.ch</a>></p>
<p>__doc__ = """The pyh.py module is the core of the PyH package. PyH lets you<br>generate HTML tags from within your python code.<br>See <a href="http://code.google.com/p/pyh/">http://code.google.com/p/pyh/</a> for documentation.<br>"""<br>__author__ = "Emmanuel Turlay <<a href="mailto:turlay@cern.ch">turlay@cern.ch</a>>"<br>__version__ = '$Revision: 43 $'<br>__date__ = '$Date$'</p>
<p>from sys import _getframe, stdout, modules, version<br>nOpen={}</p>
<p>nl = '/n'<br>doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "<a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd%22>/n'">http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">/n'</a><br>charset = '<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />/n'</p>
<p>tags = ['html', 'body', 'head', 'link', 'meta', 'div', 'p', 'form', 'legend', <br> 'input', 'select', 'span', 'b', 'i', 'option', 'img', 'script',<br> 'table', 'tr', 'td', 'th', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',<br> 'fieldset', 'a', 'title', 'body', 'head', 'title', 'script', 'br', 'table','font']</p>
<p>selfClose = ['input', 'img', 'link', 'br']</p>
<p>class Tag(list):<br> tagname = ''<br><br> def __init__(self, *arg, **kw):<br> self.attributes = kw<br> if self.tagname : <br> name = self.tagname<br> self.isSeq = False<br> else: <br> name = 'sequence'<br> self.isSeq = True<br> self.id = kw.get('id', name)<br> #self.extend(arg)<br> for a in arg: self.addObj(a)</p>
<p> def __iadd__(self, obj):<br> if isinstance(obj, Tag) and obj.isSeq:<br> for o in obj: self.addObj(o)<br> else: self.addObj(obj)<br> return self<br><br> def addObj(self, obj):<br> if not isinstance(obj, Tag): obj = str(obj)<br> id=self.setID(obj)<br> setattr(self, id, obj)<br> self.append(obj)</p>
<p> def setID(self, obj):<br> if isinstance(obj, Tag):<br> id = obj.id<br> n = len([t for t in self if isinstance(t, Tag) and t.id.startswith(id)])<br> else:<br> id = 'content'<br> n = len([t for t in self if not isinstance(t, Tag)])<br> if n: id = '%s_%03i' % (id, n)<br> if isinstance(obj, Tag): obj.id = id<br> return id</p>
<p> def __add__(self, obj):<br> if self.tagname: return Tag(self, obj)<br> self.addObj(obj)<br> return self</p>
<p> def __lshift__(self, obj):<br> self += obj<br> return obj</p>
<p> def render(self):<br> result = ''<br> if self.tagname:<br> result = '<%s%s%s>' % (self.tagname, self.renderAtt(), self.selfClose()*' /')<br> if not self.selfClose():<br> for c in self:<br> if isinstance(c, Tag):<br> result += c.render()<br> else: result += c<br> if self.tagname: <br> result += '</%s>' % self.tagname<br> result += '/n'<br> return result</p>
<p> def renderAtt(self):<br> result = ''<br> for n, v in self.attributes.iteritems():<br> if n != 'txt' and n != 'open':<br> if n == 'cl': n = 'class'<br> result += ' %s="%s"' % (n, v)<br> return result</p>
<p> def selfClose(self):<br> return self.tagname in selfClose <br><br>def TagFactory(name):<br> class f(Tag):<br> tagname = name<br> f.__name__ = name<br> return f</p>
<p>thisModule = modules[__name__]</p>
<p>for t in tags: setattr(thisModule, t, TagFactory(t)) </p>
<p>def ValidW3C():<br> out = a(img(src='http://www.w3.org/Icons/valid-xhtml10', alt='Valid XHTML 1.0 Strict'), href='http://validator.w3.org/check?uri=referer')<br> return out</p>
<p>class PyH(Tag):<br> tagname = 'html'<br><br> def __init__(self, name='MyPyHPage'):<br> self += head()<br> self += body()<br> self.attributes = dict(xmlns='http://www.w3.org/1999/xhtml', lang='en')<br> self.head += title(name)</p>
<p> def __iadd__(self, obj):<br> if isinstance(obj, head) or isinstance(obj, body): self.addObj(obj)<br> elif isinstance(obj, meta) or isinstance(obj, link): self.head += obj<br> else:<br> self.body += obj<br> id=self.setID(obj)<br> setattr(self, id, obj)<br> return self</p>
<p> def addJS(self, *arg):<br> for f in arg: self.head += script(type='text/javascript', src=f)</p>
<p> def addCSS(self, *arg):<br> for f in arg: self.head += link(rel='stylesheet', type='text/css', href=f)<br><br> def printOut(self,file=''):<br> if file: f = open(file, 'w')<br> else: f = stdout<br> f.write(doctype)<br> f.write(self.render())<br> f.flush()<br> if file: f.close()<br><br>class TagCounter:<br> _count = {}<br> _lastOpen = []<br> for t in tags: _count[t] = 0<br> def __init__(self, name):<br> self._name = name<br> def open(self, tag):<br> if isLegal(tag): <br> self._count[tag] += 1<br> self._lastOpen += [tag]<br> def close(self, tag):<br> if isLegal(tag) and self._lastOpen[-1] == tag: <br> self._count[tag] -= 1<br> self._lastOpen.pop()<br> else:<br> print 'Cross tagging is wrong'<br> def isAllowed(self, tag, open):<br> if not open and self.isClosed(tag):<br> print 'TRYING TO CLOSE NON-OPEN TAG: %s' % tag<br> return False<br> return True<br> def isOpen(self, tag):<br> if isLegal(tag): return self._count[tag]<br> def isClosed(self, tag):<br> if isLegal(tag): return not self._count[tag]</p>
<p> <br>def isLegal(tag):<br> if tag in tags: return True<br> else:<br> print 'ILLEGAL TAG: %s' % tag<br> return False<br><strong>第二步,写和DB交互的代码,通常写报表都需要从数据库或其他数据元获取数据。我的比较简单,源代码如下</strong></p>
<p>#coding=utf-8<br>import loadmylib<br>import dbunit_mysql<br>from pyh import *</p>
<p>class dbreport:<br>def __init__(self,dbinfo='report',project='aliuid',suitid=None):<br>self.db = dbunit_mysql.DBUnit(dbinfo,project)<br>self.suitid = suitid<br>if self.suitid <= 0:<br>print "suitid must not be none"<br>return<br>#<br>def get_taskresult_records(self):<br>try:<br>suitresult = self.db.read("SELECT * FROM ex_suit e where suitid =%d"%self.suitid)<br>taskid = suitresult[0]['taskid']<br>taskresult = self.db.read("select * from task where taskid = %d"%int(taskid))<br>return taskresult[0]<br>except:<br>print "getsuitreport error"</p>
<p><br>def get_groupresult_records(self):<br>try:<br>groupresult = self.db.read("SELECT * FROM ex_group where suitid =%d"%self.suitid)<br>return groupresult<br>except:<br>print "getgroupreport error"<br><br><br>def get_failedcase_records(self):<br>try:<br>sqlstr = "SELECT e.*,f.testgroupname FROM ex_case e left join ex_group f on e.testgroupid = f.testgroupid where f.suitid=%d and e.status =1 order by testcaseid"%self.suitid<br>groupresult = self.db.read(sqlstr)<br>return groupresult<br>except:<br>print "getgroupreport error"<br><br>def get_totalcase_records(self):<br>try:<br>sqlstr = "SELECT e.*,f.testgroupname FROM ex_case e left join ex_group f on e.testgroupid = f.testgroupid where f.suitid=%d order by testcaseid"%self.suitid<br>groupresult = self.db.read(sqlstr)<br>return groupresult<br>except:<br>print "getgroupreport error"</p>
<p>def getcaseresult():<br>mytab.attributes[''] = '';<br>pass</p>
<p><br>if __name__ == '__main__':<br>dbrp = dbreport(suitid=12)<br>result = dbrp.get_failedcase_records()<br>result1 = dbrp.get_totalcase_records()<br>print len(result)<br>print result<br>print result1<br><strong>第三步,自然是生成报表的代码了。源代码如下</strong></p>
<p>#coding=utf-8<br>import loadmylib<br>import dbunit_mysql<br>from pyh import *<br>import dbreport<br>import commonfunc<br>import config</p>
<p>class report:<br>def __init__(self,dbinfo='report',project='aliuid',suitid=None):<br>self.page = PyH('%s test report'%project)<br>self.page << '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'<br>self.dbinfo = dbinfo<br>self.project = project<br>self.drp = dbreport.dbreport(dbinfo,project,suitid)</p>
<p>#设定表格的格式<br>def tablecss(self,table = None,width='90%'):<br>table.attributes['cellSpacing'] = 1;<br>table.attributes['cellPadding'] = 1;<br>table.attributes['border'] = 1;<br>table.attributes['borderColor'] = '#666666';<br>table.attributes['width'] = width;<br>#set colum title bgcolor<br>def tr_title_css(self,tr = None):<br>tr.attributes['bgcolor'] = '#CCCC00';</p>
<p>#get summary info<br>def gentask_html(self):<br>#get taskresult from mysqldb<br>taskresult = self.drp.get_taskresult_records()<br>sum_div = div(b('.摘要'), id='myCSSid1') <br>self.page << sum_div <br>interfaces = taskresult['modules']<br>num_interface = len(interfaces.split(','))<br>totalcase = int(taskresult['totalcase'])<br>failedcase = int(taskresult['failedcase'])<br>successcase = totalcase - failedcase<br>tab_task = self.page << table()<br>self.tablecss(tab_task)<br>title_tr_task = tab_task << tr()<br>self.tr_title_css(title_tr_task)<br>#add task column title<br>title_tr_task << td('测试模块数') <br>title_tr_task << td('通过用例数')<br>title_tr_task << td('失败用例数')<br>title_tr_task << td('总共用例数')<br>#add column value<br>value_tr_task = tab_task << tr()<br>value_tr_task << td('%d'%num_interface)<br>value_tr_task << td('%d'%successcase)<br>value_tr_task << td('%d'%failedcase)<br>value_tr_task << td('%d'%totalcase)<br>self.page.printOut('test.html') <br>self.page << br()</p>
<p><br>def gengroupreport(self):<br>testgroups = self.drp.get_groupresult_records() <br>sum_div = div(b('.模块测试报告'), id='mydiv2') <br>self.page << sum_div <br>tab_group = self.page << table()<br>self.tablecss(tab_group)<br>title_tr_group = tab_group << tr()<br>self.tr_title_css(title_tr_group)<br>#add task column title<br>title_tr_group << td('模块名称') <br>title_tr_group << td('测试结果')<br>title_tr_group << td('通过用例数')<br>title_tr_group << td('失败用例数')<br>title_tr_group << td('总共用例数')<br>for i in range(len(testgroups)):<br>testgroup = testgroups[i]<br>groupname = testgroup['testgroupname']<br>groupstatus = int(testgroup['status'])<br>totalcase = int(testgroup['totalcase'])<br>failedcase = int(testgroup['failedcase'])<br>successcase = totalcase - failedcase<br>#add column value<br>value_tr_group = tab_group << tr()<br>value_tr_group << td('%s'%groupname)<br>if groupstatus == 0: <br>value_tr_group << td('Pass')<br>else:<br>value_tr_group << td('Failed')<br>value_tr_group << td('%d'%successcase)<br>value_tr_group << td('%d'%failedcase)<br>value_tr_group << td('%d'%totalcase)<br>self.page << br()<br><br>def gen_failedcase_report(self):<br>failedcases = self.drp.get_failedcase_records()<br>sum_div = div(b('.失败用例列表'), id='mydiv2') <br>self.page << sum_div <br>tab_failed_case = self.page << table()<br>self.tablecss(tab_failed_case)<br>title_tr_failed_case = tab_failed_case << tr()<br>self.tr_title_css(title_tr_failed_case)<br>#add task column title<br>title_tr_failed_case << td('用例编号') <br>title_tr_failed_case << td('模块名称')<br>title_tr_failed_case << td('用例说明')<br>title_tr_failed_case << td('用例等级')<br>title_tr_failed_case << td('测试结果')<br>for i in range(len(failedcases)):<br>testcase = failedcases[i]<br>casecode = testcase['testcasename']<br>groupname = testcase['testgroupname']<br>description = testcase['description']<br>level = testcase['caselevel']<br>status = int(testcase['status'])<br>#add column value<br>value_tr_failed_case = tab_failed_case << tr()<br>value_tr_failed_case << td('%s'%casecode)<br>value_tr_failed_case << td('%s'%groupname)<br>value_tr_failed_case << td('%s'%description.encode('utf-8'))<br>value_tr_failed_case << td('%s'%level)<br>if status == 0: <br>value_tr_failed_case << td('Pass')<br>else:<br>value_tr_failed_case << td('Failed')<br>self.page << br()</p>
<p>def gen_totalcase_report(self):<br>totalcases = self.drp.get_totalcase_records()<br>sum_div = div(b('.所有用例列表'), id='mydiv4') <br>self.page << sum_div <br>tab_total_case = self.page << table()<br>self.tablecss(tab_total_case)<br>title_tr_total_case = tab_total_case << tr()<br>self.tr_title_css(title_tr_total_case)<br>#add task column title<br>title_tr_total_case << td('用例编号') <br>title_tr_total_case << td('模块名称')<br>title_tr_total_case << td('用例说明')<br>title_tr_total_case << td('用例等级')<br>title_tr_total_case << td('测试结果')<br>for i in range(len(totalcases)):<br>testcase = totalcases[i]<br>casecode = testcase['testcasename']<br>groupname = testcase['testgroupname']<br>description = testcase['description']<br>level = testcase['caselevel']<br>status = int(testcase['status'])<br>#add column value<br>value_tr_total_case = tab_total_case << tr()<br>value_tr_total_case << td('%s'%casecode)<br>value_tr_total_case << td('%s'%groupname)<br>value_tr_total_case << td('%s'%description.encode('utf-8'))<br>value_tr_total_case << td('%s'%level)<br>if status == 0: <br>value_tr_total_case << td('Pass')<br>else:<br>value_tr_total_case << td('Failed')<br>self.page << br()<br></p>
<p>def getdev_build_info(self,section='build_dev'):<br>import os<br>build_dev = section<br>self.build_dev_info = config.SysConfig(self.project).getdbconnectinfo(build_dev)<br>host = self.build_dev_info['host']<br>user = self.build_dev_info['user']<br>pwd = self.build_dev_info['password']<br>source = self.build_dev_info['source']<br>result = commonfunc.ssh_cmd(host,user,pwd,"svn info %s"%source)<br>lresult = result.split("/r/n")<br>url = lresult[2]<br>reversion = lresult[5]<br>last_author = lresult[8]<br>last_date = lresult[10]<br>return lresult</p>
<p>def genbuildreport(self):<br>dev_info = self.getdev_build_info('build_dev')<br>test_info = self.getdev_build_info('build_test')<br><br>build_div = div(b('.版本信息'), id='mydiv5') <br>self.page << build_div <br>tab_build = self.page << table()</p>
<p>self.tablecss(tab_build,'70%')<br>title_tr_build = tab_build << tr()<br>self.tr_title_css(title_tr_build)<br>#add task column title<br>title_td = title_tr_build << td('开发代码版本信息') <br>title_td.attributes['colspan'] = '1';<br><br>#add column value<br>value_tr_build = tab_build << tr()<br>td_dev = value_tr_build << td()<br>#td_dev.attributes['font'] = 'size =1'<br>td_dev = td_dev << font()<br>td_dev.attributes['size'] = '2'<br>pt = td_dev << p()<br>pt << dev_info[2].strip()<br>pt <<br()<br>pt << dev_info[5].strip()<br>pt <<br()<br>pt <<dev_info[8].strip()<br>pt <<br()<br>pt <<dev_info[10].strip()<br><br>title_tr_build = tab_build << tr()<br>self.tr_title_css(title_tr_build)<br>#add task column title<br>title_td = title_tr_build << td('测试代码版本信息')<br>title_td.attributes['colspan'] = '1';<br>#add column value<br>value_tr_build = tab_build << tr()<br>td_test = value_tr_build << td()<br>td_test = td_test << font()<br>td_test.attributes['size'] = '2'<br>pt = td_test << p()<br>pt << test_info[2].strip()<br>pt <<br()<br>pt << test_info[5].strip()<br>pt <<br()<br>pt << test_info[8].strip()<br>pt <<br()<br>pt << test_info[10].strip()<br>pt <<br()<br>self.page << br()</p>
<p>def genreport(self,filename='test.html'):<br>self.genbuildreport()<br>self.gentask_html()<br>self.gengroupreport()<br>self.gen_failedcase_report()<br>self.gen_totalcase_report()<br>self.page.printOut('test.html') <br><br></p>
<p>if __name__ == '__main__':<br>file = 'first.html'<br>rp = report(suitid=12)<br>rp.genreport(file)</p>
<p></p>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值