1. 程式人生 > >介面自動化測試報告html模板

介面自動化測試報告html模板

研究了下好幾個介面自動化報告的模板,自己改造了個帶餅圖的介面自動化模板,先貼報告吧~



在貼程式碼如下:


# *-*coding:utf-8*-*

"""
@version: Python3.4.4
@author: Hszhang
@time: 2017/6/14 16:34

- 使用bottle來動態生成html

    - https://www.reddit.com/r/learnpython/comments/2sfeg0/using_template_engine_with_python_for_generating/

"""

from bottle import template
import webbrowser
import json
import sys

html_template = u"""
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head>
    <title>介面測試報告</title>
    <meta name="generator" content="HTMLTestRunner 0.8.2.2"/>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
    <script src="http://libs.baidu.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>

    <!-- 引入 echarts.js -->
    <script type="text/javascript" src="http://echarts.baidu.com/gallery/vendors/echarts/echarts-all-3.js"></script>
    <script type="text/javascript" src="http://echarts.baidu.com/gallery/vendors/echarts-stat/ecStat.min.js"></script>
    <script type="text/javascript" src="http://echarts.baidu.com/gallery/vendors/echarts/extension/dataTool.min.js"></script>

    <style type="text/css" media="screen">
        body {
            margin: 0;
            font-family: "Arial", "Microsoft YaHei", "黑體", "宋體", sans-serif;
            font-size: 18px;
            line-height: 1.5;
            line-height: 1.5;
            color: #333333;
        }
        
        .table {
            margin-bottom: 1px;
            width: 100%;
        }
        
        .hiddenRow {
            display: none;
        }
        
        .container-fluid {
            padding-right: 120px;
            padding-left: 120px;
        }
        
        .nav-tabs li {
            width: 186px;
            text-align: center;
        }
    </style>
</head>

<body >
    <script language="javascript" type="text/javascript">

    function showClassDetail(detail_id, hiddenRow_id, class_type) {
        console.log(document.getElementById(hiddenRow_id).className)
    
        if ('詳細' ==  document.getElementById(detail_id).innerText) {
            if ('all' == class_type) {
                document.getElementById(hiddenRow_id).className = 'all';
            }
            else if ('success' == class_type) {
                document.getElementById(hiddenRow_id).className = 'success';
            }
            else if ('error' == class_type) {
                document.getElementById(hiddenRow_id).className = 'error';
            }
            else{
                document.getElementById(hiddenRow_id).className = 'untreaded';
            }
            document.getElementById(detail_id).innerText = "收起"
        }
        else {
            document.getElementById(detail_id).innerText = "詳細"
            document.getElementById(hiddenRow_id).className = 'hiddenRow';
        }
    }
    
    </script>

    <div class="container-fluid">
        <div class="page-header">
            <h1 class="text-primary" style="font-size:45px;line-height:75px">介面自動化測試報告</h1>
        </div>
    
        <div class="col-md-12">
            <div class="col-md-4" style="Background-Color:#F5F5F5; height:300px">
                <h3 style="line-height:25px">測試基本資訊</h3>
                <table class="table table-hover table-bordered" style="width:100% height:11px">
                    <tbody>
                        <tr class="info">
                            <td class="text-center">開始時間</td>
                            <td class="text-center">{{start_time}}</td>
                        </tr>
                        <tr class="info">
                            <td class="text-center">結束時間</td>
                            <td class="text-center">{{end_time}}</td>
                        </tr>
                        <tr class="info">
                            <td class="text-center">測試用時</td>
                            <td class="text-center">{{used_time}}</td>
                        </tr>
                        <tr class="info">
                            <td class="text-center">總用例數</td>
                            <td class="text-center">{{sum_all_cases}}</td>
                        </tr>
                        <tr class="info">
                            <td class="text-center">執行用例數</td>
                            <td class="text-center">{{sum_executed_cases}}</td>
                        </tr>
                        <tr class="info">
                            <td class="text-center">跳過用例數</td>
                            <td class="text-center">{{sum_untreaded_cases}}</td>
                        </tr>
                    </tbody>
                </table>
            </div>
    
            <div class="col-md-8">
                <!-- 為ECharts準備一個具備大小(寬高)的Dom -->
                <div id="main" style="height:300px;"></div>
                <script type="text/javascript">
                    var myChart = echarts.init(document.getElementById('main'));
                    var option = {
                    backgroundColor: '#F5F5F5', //背景色
    
                    title: {
                        text: '測試統計資料',
                        x: 'center'
                    },
    
                    legend: {
                        orient: 'vertical',
                        x: 'left',
                        data: ['成功', '失敗', '未檢驗']
                    },
    
                    color: ['#3c763d', '#a94442', '#0099CC'],
    
                    calculable: true,
    
                    series: [{
                        name: '測試結果',
                        type: 'pie',
                        radius: '55%',
                        center: ['50%', '60%'],
                        startAngle: 135,
                        data: [{
                            value: {{right_sum}},
                            name: '成功',
                            itemStyle: {
                                normal: {
                                    label: {
                                        formatter: '{b} : {c} ({d}%)',
                                        textStyle: {
                                            align: 'left',
                                            fontSize: 15,
                                        }
                                    },
                                    labelLine: {
                                         length: 40,
                                    }
                                 }
                            }
                        }, {
                            value: {{error_sum}},
                            name: '失敗',
                            itemStyle: {
                                normal: {
                                    label: {
                                        formatter: '{b} : {c} ({d}%)',
                                        textStyle: {
                                            align: 'right',
                                            fontSize: 15,
                                        }
                                    },
                                    labelLine: {
                                        length: 40,
                                        }
                                    }
                                }
                            }, {
                            value: {{untreated_sum}},
                            name: '未檢驗',
                            itemStyle: {
                                normal: {
                                    label: {
                                        formatter: '{b} : {c} ({d}%)',
                                        textStyle: {
                                            align: 'right',
                                            fontSize: 15,
                                        }
                                   },
                                    labelLine: {
                                        length: 40,
                                        }
                                   }
                               }
                           }],
                        }]
                    };
                    // 為echarts物件載入資料
                    myChart.setOption(option);
                </script>
            </div>
        </div>    
"""

REPORT_TMPL_Lable = '''
    <div><span>&nbsp;</span></div>

    <div class="col-md-12">
        <div class="tabbable" id="tabs-957640">
            <ul class="nav nav-tabs">
                <li class="active">
                    <a href="#panel-0" data-toggle="tab" style="Background-Color: #428bca; color: #fff;">全  部 ({})</a>
                </li>
                <li>
                    <a href="#panel-1" data-toggle="tab" style="Background-Color: #d9534f; color: #fff;">成  功 ({})</a>
                </li>
                <li>
                    <a href="#panel-2" data-toggle="tab" style="Background-Color: #5cb85c; color: #fff;">失  敗 ({})</a>
                </li>
                <li>
                    <a href="#panel-3" data-toggle="tab" style="Background-Color: #5bc0de; color: #fff;">未驗證 ({})</a>
                </li>
            </ul>
        </div>
        <div class="tab-content">
            <div class="tab-pane active" id="panel-0">
                <table class="table table-hover table-bordered">
{}
                </table>
            </div>


            <div class="tab-pane" id="panel-1">
                <table class="table table-hover table-bordered">
{}
                </table>
            </div>


            <div class="tab-pane" id="panel-2">
                <table class="table table-hover table-bordered">
{}
                </table>
            </div>


            <div class="tab-pane" id="panel-3">
                <table class="table table-hover table-bordered">
{}
                </table>
            </div>
        </div>
    </div>


</div>
</body>
</html>
'''


REPORT_TMPL_Title = '''
            <table class="table table-hover table-bordered" style="Background-Color:#dff0d8">
                <thead>
                    <colgroup>
{}
                    </colgroup>
                    <tr>
{}
                    </tr>
                </thead>
                <tbody></tbody>
            </table>
 '''


REPORT_Title_Width = '''                         <col width='{}%'/>
'''


REPORT_Title_Lable = '''                         <td class="text-center"  style="Background-Color:#dff0d8">{}</td>
'''


REPORT_Table_Data = '''                           <td class="text-center">{}</td>
'''


REPORT_Table_Detail = '''                           <td class="text-center"><a href="javascript:showClassDetail('{}','{}', '{}')" class="detail" id = "{}">詳細</a></td>
'''


EXPORT_Detali_text = '''                   <tr class='hiddenRow' id="{}" >
                       <td colspan='{}'>
                           <div>
                               <pre class="text-left">
{}
                               </pre>
                           </div>
                       </td>
                   </tr> 
'''


class HTML_REPORT:
    def __init__(self, html_title, pie_theme, test_info, report_table_title, report_cases):
        '''
        @parameter html_title:HTML標題,字串型別,如html_title = u'介面測試報告'
        @parameter pie_theme:,餅圖名稱,字串型別,pie_theme = u'介面資料統計'
        @parameter test_info:,餅圖資料統計,列表型別,長度 = 6,如test_info = ['2016-12-02 15:59:17', '2016-12-02 16:10:22', '11 分 4 秒', len(report_cases['all_cases']), len(report_cases['right_cases']) + len(report_cases['error_cases']), len(report_cases['untreaded_cases'])]
        @parameter report_table_title:介面表格標題,列表型別,可以自定義,report_cases = ['專案名稱', '用例編號', '用例名稱', '介面地址', '介面方法', '測試結果', '詳細資訊']
        @parameter report_cases:介面測試結果記錄,字典格式且key不能變,report_cases = {'all_cases':[['WEB理財', '1', '登入', 'login', 'post', 'pass', '詳細資訊', ''],['WEB理財', '2', '產品列表', 'list', 'post', 'error', '詳細資訊', '']],
                                                                            'right_cases':[['WEB理財', '1', '登入', 'login', 'post', 'pass', '詳細資訊', '']],
                                                                            'error_cases':[['WEB理財', '2', '產品列表', 'list', 'post', 'error', '詳細資訊', '']],
                                                                            'untreaded_cases':[['WEB理財', '3', '測試', 'login', 'post', '/', '詳細資訊', '']]
                                                                            }
        '''
        if isinstance(html_title, str) and len(html_title) > 0:
            self.html_title = html_title
        else:
            self.html_title = u'介面測試報告'
        if isinstance(pie_theme, str) and len(pie_theme) > 0:
            self.pie_theme = pie_theme
        else:
            self.theme = u'介面資料統計'
        if isinstance(report_table_title, list) and len(report_table_title) > 0:
            self.report_table_title = report_table_title
        else:
            print('nothing of report_table_title.')
            sys.exit(0)
        if isinstance(test_info, list) and 6 == len(test_info):
            self.test_info = test_info
        else:
            print('nothing of test_info.')
            sys.exit(0)
        if isinstance(report_cases, dict) and len(report_cases) > 0:
            self.report_cases = report_cases
            self.pie_sum_number = {'right_sum': len(report_cases['right_cases']) ,'error_sum': len(report_cases['error_cases']), 'untreated_sum': len(report_cases['untreaded_cases'])}
        else:
            print('nothing of report_cases or length is not 6.')
            sys.exit(0)


    def packagedCases(self, export_lable_title, data_key, class_name, pannel_num):
        cases_num  = 1
        cases_packaged = ''
        cases_packaged = ''.join([cases_packaged,\
                                  '                   <tr class="{}">\n'.format(class_name),\
                                  export_lable_title,
                                  '                   </tr>\n'])
        for data_case in self.report_cases[data_key]:
            detail_id = ''.join([pannel_num, '-detail-', str(cases_num)])
            hidden_id = ''.join([pannel_num, '-hidden-', str(cases_num)])
            cases_num += 1
            cases_packaged = ''.join([cases_packaged, '                   <tr class="{}">\n'.format(class_name)])
            for data in data_case[:-1]:
                if '詳細' == data:
                    cases_packaged = ''.join([cases_packaged, REPORT_Table_Detail.format(detail_id, hidden_id, 'success', detail_id)])
                else:
                    cases_packaged = ''.join([cases_packaged, REPORT_Table_Data.format(data)])
            cases_packaged = ''.join([cases_packaged, '                   </tr>\n'])
            cases_packaged = ''.join([cases_packaged, EXPORT_Detali_text.format(hidden_id, len(data_case) - 1, data_case[-1])])
        return cases_packaged

    def genHtmlReport(self, html_template):
        export_lable_title = ''
        for lable_tile in self.report_table_title:
            export_lable_title = ''.join([export_lable_title, REPORT_Title_Lable.format(lable_tile)])

        str_right_datas = ''
        str_untreated_cases = ''
        str_error_cases = ''
        str_all_cases = ''

        for data_key in self.report_cases.keys():

            if 'right_cases' == data_key:
                str_right_datas = self.packagedCases(export_lable_title, data_key, 'success', 'panel1')
            elif 'untreaded_cases' == data_key:
                str_untreated_cases = self.packagedCases(export_lable_title, data_key, 'untreaded', 'panel3')
            elif 'error_cases' == data_key:
                str_error_cases = self.packagedCases(export_lable_title, data_key, 'error', 'panel2')
            else:
                str_all_cases = self.packagedCases(export_lable_title, data_key, 'all', 'panel0')
                '''
                right_cases_num  = 1
                str_right_datas = ''.join([str_right_datas,\
                                            '                   <tr class="success">\n',\
                                            export_lable_title,
                                            '                   </tr>\n'])
                for data_case in self.report_cases[data_key]:
                    right_detail_id = ''.join(['panel1-detail-', str(right_cases_num)])
                    right_hidden_id = ''.join(['panel1-hidden-', str(right_cases_num)])
                    right_cases_num += 1
                    str_right_datas = ''.join([str_right_datas, '                   <tr class="success">\n'])
                    for data in data_case[:-1]:
                        if '詳細' == data:
                            str_right_datas = ''.join([str_right_datas, REPORT_Table_Detail.format(right_detail_id, right_hidden_id, 'success', right_detail_id)])
                        else:
                            str_right_datas = ''.join([str_right_datas, REPORT_Table_Data.format(data)])
                    str_right_datas = ''.join([str_right_datas, '                   </tr>\n'])
                    str_right_datas = ''.join([str_right_datas, EXPORT_Detali_text.format(right_hidden_id, len(data_case) - 1, data_case[-1])])

            elif 'untreaded_cases' == data_key:
                str_untreated_cases = ''.join([str_untreated_cases,\
                                                '                   <tr class="untreaded">\n',\
                                                export_lable_title,
                                                '                   </tr>\n'])
                for data_case in self.report_cases[data_key][:-1]:
                    str_untreated_cases = ''.join([str_untreated_cases, '                   <tr class="untreaded">\n'])
                    for data in data_case:
                        if '詳細' in data:
                            str_untreated_cases = ''.join([str_untreated_cases,REPORT_Table_Detail.format(data)])
                        else:
                            str_untreated_cases = ''.join([str_untreated_cases, REPORT_Table_Data.format(data)])
                    str_untreated_cases = ''.join([str_untreated_cases, '                   </tr>\n'])
            elif 'error_cases' == data_key:
                str_error_cases = ''.join([str_error_cases,\
                                            export_lable_title,
                                            '                   <tr class="error">\n',\
                                             '                    </tr>\n'])
                for data_case in self.report_cases[data_key][:-1]:
                    str_error_cases = ''.join([str_error_cases, '                   <tr class="error">\n'])
                    for data in data_case:
                        if '詳細' in data:
                            str_error_cases = ''.join([str_error_cases,REPORT_Table_Detail.format(data)])
                        else:
                            str_error_cases = ''.join([str_error_cases, REPORT_Table_Data.format(data)])
                    str_error_cases = ''.join([str_error_cases, '                   </tr>\n'])
            elif 'all_cases' == data_key:
                str_all_cases = ''.join([str_all_cases,\
                                          '                   <tr class="all">\n',\
                                          export_lable_title,
                                          '                   </tr>\n'])
                for data_case in self.report_cases[data_key][:-1]:
                    str_all_cases = ''.join([str_all_cases, '                   <tr class="all">\n'])
                    for data in data_case:
                        if '詳細' == data:
                            str_all_cases = ''.join([str_all_cases, REPORT_Table_Detail.format(data)])
                        else:
                            str_all_cases = ''.join([str_all_cases, REPORT_Table_Data.format(data)])
                    str_all_cases = ''.join([str_all_cases, '                   </tr>\n'])
            '''
        export_lable_datas = REPORT_TMPL_Lable.format(len(report_cases['all_cases']),len(report_cases['right_cases']),len(report_cases['error_cases']),len(report_cases['untreaded_cases']),\
                                                      str(str_all_cases[0:-1]),\
                                                      str(str_right_datas[0:-1]),\
                                                      str(str_error_cases[0:-1]),\
                                                      str(str_untreated_cases[0:-1]))

        html_template = ''.join([html_template, export_lable_datas])

        html = template(html_template, report_title = self.html_title, theme = self.pie_theme,\
                        start_time = self.test_info[0], end_time = self.test_info[1], used_time = self.test_info[2], sum_all_cases = self.test_info[3], sum_executed_cases = self.test_info[4], sum_untreaded_cases = self.test_info[5],\
                        right_sum = self.pie_sum_number['right_sum'], error_sum = self.pie_sum_number['error_sum'], untreated_sum = self.pie_sum_number['untreated_sum'])
        return html

if __name__ == '__main__':
    report_title = u'介面測試報告'
    theme = u'介面資料統計'

    report_table_title = ['專案名稱', '用例編號', '用例名稱', '介面地址', '介面方法', '測試結果', '詳細資訊']


    case_detail = '''
sim_card_service.get_flow_by_serial Test failure!
Because of : Data check failure,AssertionError!
Data Should : sim_card_service.get_flow_by_serial
Data Actually : sim_card_service.get_flow_by_serial , 6.4413928985596


Response Json tree:
{
    "msg": {
        "message": "failed",
        "code": -1,
        "data": "該號碼不存在"
    },
    "code": -1,
    "trace": "sim_card_service.get_flow_by_serial , 6.4413928985596"
}
'''
    report_cases = {'all_cases':[\
                                       ['理財', '1', '登入', 'lo144444444444444444444444444444444444444444444444444444444444444gin', 'post', 'Pass', '詳細', case_detail],\
                                       ['WEB理財', '2', '產品列表', 'list', 'post', 'Fail', '詳細', case_detail],\
                                       ['理財', '3', '測試', 'login', 'po6666666666666666666666666666666666666666666666666666st', '/', '詳細', case_detail]\
                                 ],
                'right_cases':[['理財', '1', '登入', 'login', 'po22222222222222222222222222222st', 'Pass', '詳細', case_detail]],
                'error_cases':[['理財', '2', '產品列表', 'list', 'pos5555555555555555555555t', 'Fail', '詳細', case_detail]],
                'untreaded_cases':[['WEB理財', '3', '測試', 'login', 'po6666666666666666666666666666666666666666666666666666st', '/', '詳細', case_detail]]
                }

    test_info = ['2016-12-02 15:59:17', '2016-12-02 16:10:22', '11 分 4 秒', len(report_cases['all_cases']), len(report_cases['right_cases']) + len(report_cases['error_cases']), len(report_cases['untreaded_cases'])]

    html_report_object = HTML_REPORT(report_title, theme, test_info, report_table_title, report_cases)

    html = html_report_object.genHtmlReport(html_template)

    with open("test_demo.html",'wb') as f:
        f.write(html.encode('utf-8'))

    #使用瀏覽器開啟html

    webbrowser.open("test_demo.html")