结合 jinja2、NumPy、pyecharts 自动化生成测试报告

1:数据来源

事前已经用工具将每一条用例的运行结果与预期作了汇总、对比处理,得出本次测试的结果,存于Excel文件中。

2:报告展示

报告包含4个部分
<1>基本信息,包含本次所测试的模块名称、开始时间、结束时间。
<2>结果详情,记录每一条用例的测试结果(通过,标记绿色;不通过,标记红色)。
<3>结果概要,通过用饼图显示测试结果中通过和不通过的比例。
<4>历史,点击链接查看每一次测试的通过率变化情况(如下图)。

3:模块介绍

3.1 生成饼图

读取Excel汇总文件中Pass与Fail的各自数目后,利用 NumPy模块的 Matplotlib 绘图库,生成饼图,相关代码如下

import matplotlib.pyplot as plt
import xlrd
def getPie(source_file,target_file):
    # 读取 Excel,获取Pass与Fail的各自数目
    data = xlrd.open_workbook(filename=source_file)
    table = data.sheet_by_index(0)
    npass = 0
    nfail = 0
    i = 1
    while i < table.nrows:
        if table.cell(i, 4).value == 'Pass':
            npass += 1
        else:
            nfail += 1
        i += 1

    lable = 'Pass', 'Fail'
    sizes = [npass, nfail]
    explode = (0, 0)
    plt.pie(sizes,
            explode=explode,
            labels=lable,
            autopct='%1.1f%%',
            shadow=False,
            startangle=90,
            colors=['green', 'red'])
    plt.axis('equal')
    plt.title('Test Result')
    # 保存饼图
    plt.savefig(target_file)


if __name__ == '__main__':
    getPie(source_file='testSum.xlsx',
           target_file='Pie.jpg')
    print('successfully')

3.2 生成折线图

利用数据可视化插件pyecharts 中的Line生成html格式的折线图

from  pyecharts import Line
def getLine(d1):
    line=Line("测试记录")
    line.add("通过率", d1["TestingTime"], d1["Ratio"],is_label_show=True)
    line.render("Line.html")  # 生成本地 HTML 文件
if __name__ == '__main__':
    #历史数据
    data = {
        "TestingTime": [
            "2020-02-01" + '\\n' + "16:00",
            "2020-02-02" + '\\n' + "10:08",
            "2020-02-02" + '\\n' + "15:30",
            "2020-02-03" + '\\n' + "09:20",
            "2020-02-03" + '\\n' + "14:38"
        ],
        "Ratio": [
            0.4,
            0.45,
            0.5,
            0.6,
            0.8
        ]
    }

    getLine(data)
    print('successfully')

3.3 生成报告

利用jinja2 生成报告
首先需要一个作为模板的文件 Sample.html

<meta http-equiv="Content-Type"content="text/html;charset=utf-8">
<html align='left'>
<h1 align='center'>测试报告</h1>
    <body>
\t<table width="1700" border="0">
\t<tr>
\t<td colspan="2">
\t<h2>1:基本信息</h2> \t
\t<p>被测模块: {{module}}</p>
\t<p>测试开始时间 : {{start_time}} </p>
\t<p>测试结束时间 : {{stop_time}}  </p>
\t</td>
    </tr>
\t<tr>
\t<td style="background-color:#eeeeee;width:900px;">
    <h2>2:结果详情</h2>
\t<br></br>\t
    <table border="1"  cellspacing='0' cellpadding='0'>
    <tr align='left'>        
        <th width = "15%">用例编号</th>
        <th width = "60%">用例名称</th>
        <th width = "20%">测试结果</th>
    </tr>
    {% for item in body %}
    <tr align='left'>
        <td>{{ item.Case_ID }}</td>
        <td>{{ item.Case_Name }}</td>
\t\t{% if item.result == 'Pass'%}
\t\t<td bgcolor='green'>{{ item.result }}</td>
\t\t{% else %}
\t\t<td bgcolor='red'>{{ item.result }}</td>
\t\t{% endif%}

    </tr>
    {% endfor%}
    </table>
\t</td>
    <td style="background-color:#eeeeee;width:600px;">
    <h2>3:结果概要</h2>  
    <p>用例总数 : {{n_pass+n_fail}}</p>
\t<p>通过 : {{n_pass}}</p>
\t<p>不通过 : {{n_fail}}  </p>
\t<img src={{pie_name}}>
\t</td>\t
\t<td align="left",colspan="2" style="background-color:#eeeeee;height:50px,width:200px;">
    <h2>4:历史</h2> 
    <a href={{line_name}} target="_blank">测试记录</a>
    <br></br>
\t<br></br>
\t<br></br>
\t<br></br>
\t<br></br>
\t<br></br>
\t<br></br>
\t<br></br>
\t<br></br>
\t<br></br>
\t<br></br>
\t<br></br>
\t<br></br>\t
\t<br></br>
\t</td>
    </tr>
\t</table>
    </body>
</html>


然后执行代码如下


from jinja2 import Environment, FileSystemLoader
import xlrd

def GetResult_FromExl(filename):
    #读取Excel汇总文件
    data = xlrd.open_workbook(filename=filename)
    table=data.sheet_by_index(0)
    npass = 0
    nfail = 0
    body = []
    i=1
    while i<table.nrows:
        if table.cell(i, 4).value == 'Pass':
            npass += 1
        else:
            nfail += 1
        result = {'Case_ID': "",
                  'Case_Name': "",
                  'result': ""}
        result['Case_ID']=i
        result['Case_Name'] = table.cell(i,1).value
        result['result'] = table.cell(i, 4).value

        body.append(result)
        i+=1
    return npass,nfail,body


def generate_html(samlpe_file,
                  result_file,
                  module_name,
                  body,
                  starttime,
                  stoptime,
                  npass,
                  nfail,
                  pie_name,
                  line_name):
    env = Environment(loader=FileSystemLoader('./'))
    template = env.get_template(samlpe_file)
    with open(result_file, 'w+', encoding='utf-8') as fout:
        html_content = template.render(start_time=starttime,
                                       stop_time=stoptime,
                                       body=body,
                                       n_pass=npass,
                                       n_fail=nfail,
                                       module=module_name,
                                       pie_name=pie_name,
                                       line_name=line_name,
                                       )
        fout.write(html_content)


if __name__ == "__main__":
    npass,nfail,body=GetResult_FromExl(filename='testSum.xlsx')
    generate_html(body=body, #表格数据体
                  starttime='2020-02-03 14:30', #测试开始时间
                  stoptime='2020-02-03 14:38', #测试结束时间
                  npass=npass, #通过的用例数目
                  nfail=nfail, #不通过的用例数目
                  module_name='XXX模块', #被测试的模块名称
                  samlpe_file='Sample.html', #生成报告的模板文件
                  pie_name='Pie.jpg', #饼图文件
                  line_name='Line.html', #折线图文件
                  result_file='result.html') #最终生成的报告文件