python 生成html测试报表三步曲

发布时间:2019-08-28 09:11:06编辑:auto阅读(1673)

    最近把测试框架优化了一下,原本生成的报表时txt格式的,现在搞成html格式。主要步骤如下
    首先找个html处理工具,这样处理html会简单很多
    我网上找了一下发现phy停好用,在这里非常感谢pyh的作者
    phy源码如下
    # @file: pyh.py
    # @purpose: a HTML tag generator
    # @author: Emmanuel Turlay <turlay@cern.ch>
    __doc__ = """The pyh.py module is the core of the PyH package. PyH lets you
    generate HTML tags from within your python code.
    See http://code.google.com/p/pyh/ for documentation.
    """
    __author__ = "Emmanuel Turlay <turlay@cern.ch>"
    __version__ = '$Revision: 43 $'
    __date__ = '$Date$'
    from sys import _getframe, stdout, modules, version
    nOpen={}
    nl = '/n'
    doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">/n'
    charset = '<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />/n'
    tags = ['html', 'body', 'head', 'link', 'meta', 'div', 'p', 'form', 'legend',
    'input', 'select', 'span', 'b', 'i', 'option', 'img', 'script',
    'table', 'tr', 'td', 'th', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
    'fieldset', 'a', 'title', 'body', 'head', 'title', 'script', 'br', 'table','font']
    selfClose = ['input', 'img', 'link', 'br']
    class Tag(list):
    tagname = ''

    def __init__(self, *arg, **kw):
    self.attributes = kw
    if self.tagname :
    name = self.tagname
    self.isSeq = False
    else:
    name = 'sequence'
    self.isSeq = True
    self.id = kw.get('id', name)
    #self.extend(arg)
    for a in arg: self.addObj(a)
    def __iadd__(self, obj):
    if isinstance(obj, Tag) and obj.isSeq:
    for o in obj: self.addObj(o)
    else: self.addObj(obj)
    return self

    def addObj(self, obj):
    if not isinstance(obj, Tag): obj = str(obj)
    id=self.setID(obj)
    setattr(self, id, obj)
    self.append(obj)
    def setID(self, obj):
    if isinstance(obj, Tag):
    id = obj.id
    n = len([t for t in self if isinstance(t, Tag) and t.id.startswith(id)])
    else:
    id = 'content'
    n = len([t for t in self if not isinstance(t, Tag)])
    if n: id = '%s_%03i' % (id, n)
    if isinstance(obj, Tag): obj.id = id
    return id
    def __add__(self, obj):
    if self.tagname: return Tag(self, obj)
    self.addObj(obj)
    return self
    def __lshift__(self, obj):
    self += obj
    return obj
    def render(self):
    result = ''
    if self.tagname:
    result = '<%s%s%s>' % (self.tagname, self.renderAtt(), self.selfClose()*' /')
    if not self.selfClose():
    for c in self:
    if isinstance(c, Tag):
    result += c.render()
    else: result += c
    if self.tagname:
    result += '</%s>' % self.tagname
    result += '/n'
    return result
    def renderAtt(self):
    result = ''
    for n, v in self.attributes.iteritems():
    if n != 'txt' and n != 'open':
    if n == 'cl': n = 'class'
    result += ' %s="%s"' % (n, v)
    return result
    def selfClose(self):
    return self.tagname in selfClose

    def TagFactory(name):
    class f(Tag):
    tagname = name
    f.__name__ = name
    return f
    thisModule = modules[__name__]
    for t in tags: setattr(thisModule, t, TagFactory(t))
    def ValidW3C():
    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')
    return out
    class PyH(Tag):
    tagname = 'html'

    def __init__(self, name='MyPyHPage'):
    self += head()
    self += body()
    self.attributes = dict(xmlns='http://www.w3.org/1999/xhtml', lang='en')
    self.head += title(name)
    def __iadd__(self, obj):
    if isinstance(obj, head) or isinstance(obj, body): self.addObj(obj)
    elif isinstance(obj, meta) or isinstance(obj, link): self.head += obj
    else:
    self.body += obj
    id=self.setID(obj)
    setattr(self, id, obj)
    return self
    def addJS(self, *arg):
    for f in arg: self.head += script(type='text/javascript', src=f)
    def addCSS(self, *arg):
    for f in arg: self.head += link(rel='stylesheet', type='text/css', href=f)

    def printOut(self,file=''):
    if file: f = open(file, 'w')
    else: f = stdout
    f.write(doctype)
    f.write(self.render())
    f.flush()
    if file: f.close()

    class TagCounter:
    _count = {}
    _lastOpen = []
    for t in tags: _count[t] = 0
    def __init__(self, name):
    self._name = name
    def open(self, tag):
    if isLegal(tag):
    self._count[tag] += 1
    self._lastOpen += [tag]
    def close(self, tag):
    if isLegal(tag) and self._lastOpen[-1] == tag:
    self._count[tag] -= 1
    self._lastOpen.pop()
    else:
    print 'Cross tagging is wrong'
    def isAllowed(self, tag, open):
    if not open and self.isClosed(tag):
    print 'TRYING TO CLOSE NON-OPEN TAG: %s' % tag
    return False
    return True
    def isOpen(self, tag):
    if isLegal(tag): return self._count[tag]
    def isClosed(self, tag):
    if isLegal(tag): return not self._count[tag]

    def isLegal(tag):
    if tag in tags: return True
    else:
    print 'ILLEGAL TAG: %s' % tag
    return False
    第二步,写和DB交互的代码,通常写报表都需要从数据库或其他数据元获取数据。我的比较简单,源代码如下
    #coding=utf-8
    import loadmylib
    import dbunit_mysql
    from pyh import *
    class dbreport:
    def __init__(self,dbinfo='report',project='aliuid',suitid=None):
    self.db = dbunit_mysql.DBUnit(dbinfo,project)
    self.suitid = suitid
    if self.suitid <= 0:
    print "suitid must not be none"
    return
    #
    def get_taskresult_records(self):
    try:
    suitresult = self.db.read("SELECT * FROM ex_suit e where suitid =%d"%self.suitid)
    taskid = suitresult[0]['taskid']
    taskresult = self.db.read("select * from task where taskid = %d"%int(taskid))
    return taskresult[0]
    except:
    print "getsuitreport error"

    def get_groupresult_records(self):
    try:
    groupresult = self.db.read("SELECT * FROM ex_group where suitid =%d"%self.suitid)
    return groupresult
    except:
    print "getgroupreport error"


    def get_failedcase_records(self):
    try:
    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
    groupresult = self.db.read(sqlstr)
    return groupresult
    except:
    print "getgroupreport error"

    def get_totalcase_records(self):
    try:
    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
    groupresult = self.db.read(sqlstr)
    return groupresult
    except:
    print "getgroupreport error"
    def getcaseresult():
    mytab.attributes[''] = '';
    pass

    if __name__ == '__main__':
    dbrp = dbreport(suitid=12)
    result = dbrp.get_failedcase_records()
    result1 = dbrp.get_totalcase_records()
    print len(result)
    print result
    print result1
    第三步,自然是生成报表的代码了。源代码如下
    #coding=utf-8
    import loadmylib
    import dbunit_mysql
    from pyh import *
    import dbreport
    import commonfunc
    import config
    class report:
    def __init__(self,dbinfo='report',project='aliuid',suitid=None):
    self.page = PyH('%s test report'%project)
    self.page << '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'
    self.dbinfo = dbinfo
    self.project = project
    self.drp = dbreport.dbreport(dbinfo,project,suitid)
    #设定表格的格式
    def tablecss(self,table = None,width='90%'):
    table.attributes['cellSpacing'] = 1;
    table.attributes['cellPadding'] = 1;
    table.attributes['border'] = 1;
    table.attributes['borderColor'] = '#666666';
    table.attributes['width'] = width;
    #set colum title bgcolor
    def tr_title_css(self,tr = None):
    tr.attributes['bgcolor'] = '#CCCC00';
    #get summary info
    def gentask_html(self):
    #get taskresult from mysqldb
    taskresult = self.drp.get_taskresult_records()
    sum_div = div(b('.摘要'), id='myCSSid1')
    self.page << sum_div
    interfaces = taskresult['modules']
    num_interface = len(interfaces.split(','))
    totalcase = int(taskresult['totalcase'])
    failedcase = int(taskresult['failedcase'])
    successcase = totalcase - failedcase
    tab_task = self.page << table()
    self.tablecss(tab_task)
    title_tr_task = tab_task << tr()
    self.tr_title_css(title_tr_task)
    #add task column title
    title_tr_task << td('测试模块数')
    title_tr_task << td('通过用例数')
    title_tr_task << td('失败用例数')
    title_tr_task << td('总共用例数')
    #add column value
    value_tr_task = tab_task << tr()
    value_tr_task << td('%d'%num_interface)
    value_tr_task << td('%d'%successcase)
    value_tr_task << td('%d'%failedcase)
    value_tr_task << td('%d'%totalcase)
    self.page.printOut('test.html')
    self.page << br()

    def gengroupreport(self):
    testgroups = self.drp.get_groupresult_records()
    sum_div = div(b('.模块测试报告'), id='mydiv2')
    self.page << sum_div
    tab_group = self.page << table()
    self.tablecss(tab_group)
    title_tr_group = tab_group << tr()
    self.tr_title_css(title_tr_group)
    #add task column title
    title_tr_group << td('模块名称')
    title_tr_group << td('测试结果')
    title_tr_group << td('通过用例数')
    title_tr_group << td('失败用例数')
    title_tr_group << td('总共用例数')
    for i in range(len(testgroups)):
    testgroup = testgroups[i]
    groupname = testgroup['testgroupname']
    groupstatus = int(testgroup['status'])
    totalcase = int(testgroup['totalcase'])
    failedcase = int(testgroup['failedcase'])
    successcase = totalcase - failedcase
    #add column value
    value_tr_group = tab_group << tr()
    value_tr_group << td('%s'%groupname)
    if groupstatus == 0:
    value_tr_group << td('Pass')
    else:
    value_tr_group << td('Failed')
    value_tr_group << td('%d'%successcase)
    value_tr_group << td('%d'%failedcase)
    value_tr_group << td('%d'%totalcase)
    self.page << br()

    def gen_failedcase_report(self):
    failedcases = self.drp.get_failedcase_records()
    sum_div = div(b('.失败用例列表'), id='mydiv2')
    self.page << sum_div
    tab_failed_case = self.page << table()
    self.tablecss(tab_failed_case)
    title_tr_failed_case = tab_failed_case << tr()
    self.tr_title_css(title_tr_failed_case)
    #add task column title
    title_tr_failed_case << td('用例编号')
    title_tr_failed_case << td('模块名称')
    title_tr_failed_case << td('用例说明')
    title_tr_failed_case << td('用例等级')
    title_tr_failed_case << td('测试结果')
    for i in range(len(failedcases)):
    testcase = failedcases[i]
    casecode = testcase['testcasename']
    groupname = testcase['testgroupname']
    description = testcase['description']
    level = testcase['caselevel']
    status = int(testcase['status'])
    #add column value
    value_tr_failed_case = tab_failed_case << tr()
    value_tr_failed_case << td('%s'%casecode)
    value_tr_failed_case << td('%s'%groupname)
    value_tr_failed_case << td('%s'%description.encode('utf-8'))
    value_tr_failed_case << td('%s'%level)
    if status == 0:
    value_tr_failed_case << td('Pass')
    else:
    value_tr_failed_case << td('Failed')
    self.page << br()
    def gen_totalcase_report(self):
    totalcases = self.drp.get_totalcase_records()
    sum_div = div(b('.所有用例列表'), id='mydiv4')
    self.page << sum_div
    tab_total_case = self.page << table()
    self.tablecss(tab_total_case)
    title_tr_total_case = tab_total_case << tr()
    self.tr_title_css(title_tr_total_case)
    #add task column title
    title_tr_total_case << td('用例编号')
    title_tr_total_case << td('模块名称')
    title_tr_total_case << td('用例说明')
    title_tr_total_case << td('用例等级')
    title_tr_total_case << td('测试结果')
    for i in range(len(totalcases)):
    testcase = totalcases[i]
    casecode = testcase['testcasename']
    groupname = testcase['testgroupname']
    description = testcase['description']
    level = testcase['caselevel']
    status = int(testcase['status'])
    #add column value
    value_tr_total_case = tab_total_case << tr()
    value_tr_total_case << td('%s'%casecode)
    value_tr_total_case << td('%s'%groupname)
    value_tr_total_case << td('%s'%description.encode('utf-8'))
    value_tr_total_case << td('%s'%level)
    if status == 0:
    value_tr_total_case << td('Pass')
    else:
    value_tr_total_case << td('Failed')
    self.page << br()
    def getdev_build_info(self,section='build_dev'):
    import os
    build_dev = section
    self.build_dev_info = config.SysConfig(self.project).getdbconnectinfo(build_dev)
    host = self.build_dev_info['host']
    user = self.build_dev_info['user']
    pwd = self.build_dev_info['password']
    source = self.build_dev_info['source']
    result = commonfunc.ssh_cmd(host,user,pwd,"svn info %s"%source)
    lresult = result.split("/r/n")
    url = lresult[2]
    reversion = lresult[5]
    last_author = lresult[8]
    last_date = lresult[10]
    return lresult
    def genbuildreport(self):
    dev_info = self.getdev_build_info('build_dev')
    test_info = self.getdev_build_info('build_test')

    build_div = div(b('.版本信息'), id='mydiv5')
    self.page << build_div
    tab_build = self.page << table()
    self.tablecss(tab_build,'70%')
    title_tr_build = tab_build << tr()
    self.tr_title_css(title_tr_build)
    #add task column title
    title_td = title_tr_build << td('开发代码版本信息')
    title_td.attributes['colspan'] = '1';

    #add column value
    value_tr_build = tab_build << tr()
    td_dev = value_tr_build << td()
    #td_dev.attributes['font'] = 'size =1'
    td_dev = td_dev << font()
    td_dev.attributes['size'] = '2'
    pt = td_dev << p()
    pt << dev_info[2].strip()
    pt <<br()
    pt << dev_info[5].strip()
    pt <<br()
    pt <<dev_info[8].strip()
    pt <<br()
    pt <<dev_info[10].strip()

    title_tr_build = tab_build << tr()
    self.tr_title_css(title_tr_build)
    #add task column title
    title_td = title_tr_build << td('测试代码版本信息')
    title_td.attributes['colspan'] = '1';
    #add column value
    value_tr_build = tab_build << tr()
    td_test = value_tr_build << td()
    td_test = td_test << font()
    td_test.attributes['size'] = '2'
    pt = td_test << p()
    pt << test_info[2].strip()
    pt <<br()
    pt << test_info[5].strip()
    pt <<br()
    pt << test_info[8].strip()
    pt <<br()
    pt << test_info[10].strip()
    pt <<br()
    self.page << br()
    def genreport(self,filename='test.html'):
    self.genbuildreport()
    self.gentask_html()
    self.gengroupreport()
    self.gen_failedcase_report()
    self.gen_totalcase_report()
    self.page.printOut('test.html')

    if __name__ == '__main__':
    file = 'first.html'
    rp = report(suitid=12)
    rp.genreport(file)

关键字