# TPG **Repository Path**: phygerr/tpg ## Basic Information - **Project Name**: TPG - **Description**: TPG测试报告生成器 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-12-05 - **Last Updated**: 2022-06-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # TPG

微信联系

#### 介绍 TPG测试报告生成器 #### 个人公号 Python研究所 #### 源码 ```python from pywebio.input import * from pywebio.output import * from pywebio.pin import * from pyecharts import options as opts from pyecharts.charts import Bar from pyecharts.globals import ThemeType from pywebio import start_server from pywebio.platform import path_deploy,run_event_loop import pandas as pd import logging handler = logging.FileHandler("tpg.log") formatter= logging.Formatter("%(asctime)s - %(message)s") handler.setFormatter(formatter) def ReportGenerate(): basic_info = input_group('基础信息',[ input( '请输入版本号', name='version1', type=TEXT, placeholder='版本号,例:v3.0.1', # 占位 #value='v3.0.1', #help_text='This is help text', # 提示 required=True, # 必填 datalist=['v3.0.1', 'v3.0.2', 'v3.0.3'] # 常驻输入联想 ), input( '请输入迭代', name='version2', type=TEXT, placeholder='迭代,例:1月迭代', # 占位 #value='1月迭代', #help_text='This is help text', # 提示 required=True, # 必填 datalist=['1月迭代', '2月迭代', '3月迭代', '4月迭代', '5月迭代', '6月迭代', '7月迭代', '8月迭代', '9月迭代', '10月迭代', '11月迭代', '12月迭代'] # 常驻输入联想 ), input( '请输入起始测试时间', name='test_time1', value='2022-2-0', type=DATE, required=True, # 必填 ), input( '请输入结束测试时间', name='test_time2', value='2022-2-2', type=DATE, required=True, # 必填 ), input( '请输入测试用例链接', name='test_case_url', type=URL, required=True, # 必填 help_text='Jira上测试用例文档的链接', ), ]) issue_info = input_group('缺陷信息',[ input( label='缺陷列表URL', name='issue_url', type=URL, required=True, ), input( label='缺陷总数', name='issue_total', type=NUMBER, required=True, # 必填 value=40 ), input( label='致命的缺陷数', name='die', type=NUMBER, required=True, # 必填 value=1 ), input( label='严重的缺陷数', name='critical', type=NUMBER, required=True, # 必填 value=4 ), input( label='一般的缺陷数', name='normal', type=NUMBER, required=True, # 必填 value=8 ), input( label='建议的缺陷数', name='low', type=NUMBER, required=True, # 必填 value=10 ), input( label='关闭的缺陷数', name='closed', type=NUMBER, required=True, value=10 ), input( label='拒绝的缺陷数', name='refused', type=NUMBER, required=True, value=1 ), # input( # label='修复的缺陷数', # name='fixed', # type=NUMBER, # required=True, # value=1 # ), input( label='未解决的缺陷数', name='error', type=NUMBER, required=True, value=3 ), ]) issue_analyse = input_group('缺陷分析',[ input( label='模块1', name='portal', type=NUMBER, required=True, value=121 ), input( label='模块2', name='cmp', type=NUMBER, required=True, value=22 ), input( label='模块3', name='nova', type=NUMBER, required=True, value=12 ), input( label='模块4', name='net', type=NUMBER, required=True, value=7 ), input( label='模块5', name='storage', type=NUMBER, required=True, value=4 ), input( label='模块6', name='common', type=NUMBER, required=True, value=9 ), input( label='模块7', name='product', type=NUMBER, required=True, value=15 ), input( label='模块8', name='RDS', type=NUMBER, required=True, value=18 ), input( label='模块9', name='arch', type=NUMBER, required=True, value=0 ), input( label='模块10', name='devops', type=NUMBER, required=True, value=1 ), input( label='运维', name='ops', type=NUMBER, required=True, value=0 ), ]) issue_analyse_2 = input_group('缺陷分析-致命&严重',[ input( label='模块1', name='portal', type=NUMBER, required=True, value=1, help_text='请填写致命+严重的缺陷数' ), input( label='模块2', name='cmp', type=NUMBER, required=True, value=1 ), input( label='模块3', name='nova', type=NUMBER, required=True, value=1 ), input( label='模块4', name='net', type=NUMBER, required=True, value=1 ), input( label='模块5', name='storage', type=NUMBER, required=True, value=1 ), input( label='模块6', name='common', type=NUMBER, required=True, value=1 ), input( label='模块7', name='product', type=NUMBER, required=True, value=1 ), input( label='模块8', name='RDS', type=NUMBER, required=True, value=1 ), input( label='模块9', name='arch', type=NUMBER, required=True, value=0 ), input( label='模块10', name='devops', type=NUMBER, required=True, value=0 ), input( label='运维', name='ops', type=NUMBER, required=True, value=0 ), ]) result_info = input_group('测试结论和建议',[ textarea( label='测试结论', value='根据测试数据分析,当前版本缺陷总数较多,严重缺陷相对较少,所有缺陷均已解决,版本质量良好。', help_text='例:根据测试数据分析,当前版本缺陷总数较多,严重缺陷相对较少,所有缺陷均已解决,版本质量良好。', name='res', type=TEXT, required=True, rows=3, ), input( label='测试建议', value='继续加强代码review管控,模块7设计评审。', help_text='例:继续加强代码review管控,模块7设计评审。', name='suggest', type=TEXT, required=True, ), select( label='发布结果', value='可以发布', options=['可以发布','不可发布'], name='fb', required=True, ), input( label='缺陷主要原因', name='reason', type=TEXT, value='模块7设计缺失、需求不完整、代码BUG等导致', required=True, ), ]) # =============== xlsx转换为html table================ files = file_upload("请上传未解决的缺陷文件.xlsx", accept=['.xlsx','xls'],) pf = pd.read_excel(files.get('content')) import time times=time.strftime('%Y-%m-%d %T' , time.localtime()) test_time = '测试时间' # ===============Part One======================= put_markdown(f"# Python研究所 {basic_info['version1']} 版本 {basic_info['version2']} 测试报告").style('display:flex;justify-content: center;') put_markdown(f"## 1、概述") put_markdown(f"本测试报告为Python研究所{basic_info['version1']}版本功能测试报告;本报告目的在于评估{basic_info['version1']}/{basic_info['version2']}的基本功能是否满足发布要求。") put_markdown("本报告预期参与人员包括测试执行人员、测试负责人员、项目管理人员、模块10人员和其他开发团队成员。") # ===============Part Two======================= put_markdown("## 2、测试参考文档") put_column([ put_markdown("- [x] 需求文档"), put_markdown("- [x] 概要设计"), put_markdown("- [x] 详细设计"), put_markdown("- [x] 环境部署文档"), put_markdown("- [x] 自测报告"), put_markdown("- [x] 转测申请"), put_markdown("- [x] 测试计划"), put_markdown("- [x] 测试用例"), ] ) # ===============Part Three======================= put_markdown("## 3、测试设计") put_markdown("### 3.1、测试环境与配置") put_column( put_table([ [span('Python研究所',row=2), span('测试环境', col=2)], ['环境地址','规模'], ['IaaS', 'Python研究所','3控+3管+4模块3'], ['Portal', 'Python研究所', 'xx'], ['模块2', 'Python研究所', 'xx'], ])).style('display:flex;justify-content: center;') put_markdown("### 3.2、测试用例设计") put_markdown("测试用例的设计按场景、模块等多个层次进行用例设计。通过基础核心功能、基础非核心功能以及异常场景下的功能可用性将用例分为了P0、P1、P2、P3四种级别。") put_markdown(" - P0:基础核心功能") put_markdown(" - P1:基础高频功能") put_markdown(" - P2:基础低频功能") put_markdown(" - P3:UI布局&用户体验") put_markdown("### 3.3、测试方法") put_markdown("本次测试采用黑盒测试方法。通过手动执行功能测试用例结合自动化回归进行测试。") # ===============Part Four======================= put_markdown("## 4、测试计划") put_markdown("### 4.1、测试时间和人员") put_markdown(f" > 测试时间:{basic_info['test_time1']}-{basic_info['test_time2']}") # put_table([ # ['模块','模块3','模块5','模块4','模块8','SLB','审计','组织','运营-模块7','运营-计费','运营-其他','模块1-其他'], # ['主测试','Python研究所','Python研究所','Python研究所','Python研究所','phyger','Python研究所','Python研究所','Python研究所','Python研究所','Python研究所','all',], # ['备测试','all','phyger','phyger','phyger','Python研究所','Python研究所','all','Python研究所','Python研究所','all','all'] # ]) put_table([ ['模块3', 'Python研究所', 'all'], ['模块5', 'Python研究所', 'phyger'], ['模块4', 'Python研究所', 'phyger'], ['模块8', 'Python研究所', 'phyger'], ['ok', 'phyger', 'Python研究所'], ['ko', 'Python研究所', 'Python研究所'], ['xx', 'Python研究所', 'all'], ['运营-模块7', 'Python研究所', 'Python研究所'], ['运营-计费', 'Python研究所', 'Python研究所'], ['运营-其他', 'Python研究所', 'all'], ['模块1-其他', 'all', 'all'], ], header=['模块', '主测试', '备测试']) put_markdown("### 4.2、功能覆盖") put_link(name="1. ★历史版本存量功能",url='https://u1s1.vip',new_window=True) put_html('
') put_link(name=f"2. ★{basic_info['version2']}新增需求",url='https://u1s1.vip/#/issue',new_window=True) put_markdown("### 4.3、被测环境结构") put_table([ ['portal','aaaa','xxxxx'], ['middle','a+a','xx平台,xx和模块1的桥梁'], [span('模块1',row=13), 'xxx','xxx生命周期管理'], ['aa', 'aaaa'], ['xx', 'xxxx'], ],header=['分类','模块','概述']) put_markdown("### 4.4、测试用例") put_link(name='点击查看测试用例',url=basic_info['test_case_url'],new_window=True) # ===============Part Five====================== put_markdown("## 5、缺陷分析") put_markdown("### 5.1、缺陷概览") put_markdown(f"致命缺陷数:{issue_info['die']}").style('color: red;') put_markdown(f"严重缺陷数:{issue_info['critical']}").style('color: #ff00ff;') # ===============Picture====================== c = ( Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT)) .add_xaxis([ '已拒绝', '已解决', '未解决', '缺陷总数' ]) .add_yaxis("", [ issue_info['refused'], issue_info['closed'], issue_info['error'], issue_info['issue_total'] ]) .set_global_opts( xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=0)), title_opts=opts.TitleOpts(title="缺陷-按状态分布")) ) c.width = "100%" put_html(c.render_notebook()) # ===============Picture====================== c = ( Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT)) .add_xaxis([ '致命', '严重', '一般', '建议' ]) .add_yaxis("", [ issue_info['die'], issue_info['critical'], issue_info['normal'], issue_info['low'] ]) .set_global_opts( xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=0)), title_opts=opts.TitleOpts(title="缺陷-按严重程度分布")) ) c.width = "100%" put_html(c.render_notebook()) # put_table([ # [issue_info['critical'], issue_info['closed'], issue_info['refused'],issue_info['fixed'],issue_info['error'],issue_info['issue_total']], # ], header=['严重缺陷', '已关闭','已拒绝','已修复','未解决','缺陷总数']) put_markdown(f"本次测试总共发现问题总计{issue_info['issue_total']}个,已经关闭{issue_info['closed']}个,关闭率为{float('%.2f' %(issue_info['closed']/issue_info['issue_total']*100))}%,还剩余{issue_info['error']}个缺陷未处理。缺陷发生的主要原因为:{result_info['reason']}。") put_markdown("### 5.2、缺陷分析") put_markdown("#### 5.2.1、缺陷-按模块分布") # ===============Bar Picture 缺陷分布 ================= c = ( Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT)) .add_xaxis([ '模块1', '模块2', '模块3', '模块4', '模块5', '模块6', '模块7', '模块8', '模块9', '模块10', 'ops' ]) .add_yaxis("总缺陷", [ issue_analyse['portal'], issue_analyse['cmp'], issue_analyse['nova'], issue_analyse['net'], issue_analyse['storage'], issue_analyse['common'], issue_analyse['product'], issue_analyse['RDS'], issue_analyse['arch'], issue_analyse['devops'], issue_analyse['ops'] ]) .set_global_opts( xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)), title_opts=opts.TitleOpts(title="缺陷-按模块分布")) ) c.width = "100%" put_html(c.render_notebook()) # ===============Bar Picture 严重缺陷分布 ================= put_markdown("#### 5.2.2、严重缺陷-按模块分布") c = ( Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT)) .add_xaxis([ '模块1', '模块2', '模块3', '模块4', '模块5', '模块6', '模块7', '模块8', '模块9', '模块10', 'ops' ]) .add_yaxis("严重缺陷", [ issue_analyse_2['portal'], issue_analyse_2['cmp'], issue_analyse_2['nova'], issue_analyse_2['net'], issue_analyse_2['storage'], issue_analyse_2['common'], issue_analyse_2['product'], issue_analyse_2['RDS'], issue_analyse_2['arch'], issue_analyse_2['devops'], issue_analyse_2['ops'] ]) .set_global_opts( xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)), title_opts=opts.TitleOpts(title="严重缺陷-按模块分布")) ) c.width = "100%" put_html(c.render_notebook()) put_markdown("#### 5.2.3、未修复的缺陷列表") put_html(pf.to_html(border=0)) put_markdown("### 5.3、缺陷列表") put_link(name='点击查看缺陷列表',url=issue_info['issue_url'],new_window=True) put_markdown("## 6、测试结论和建议") put_markdown(f"{ result_info['res']}缺陷发生的主要原因为:{result_info['reason']}。") put_markdown(f"{ result_info['suggest']}") if result_info['fb']=='可以发布': put_markdown(f"当前版本质量状态:{ result_info['fb'] }").style('color: #00ff00') else: put_markdown(f"当前版本质量状态:{ result_info['fb'] }").style('color: #ff0000') #put_markdown(f"本次测试总共发现问题总计{issue_info['issue_total']}个,已经关闭{issue_info['closed']}个,关闭率为{float('%.2f' %(issue_info['closed']/issue_info['issue_total']*100))}%,还剩余{issue_info['error']}个缺陷未处理。缺陷发生的主要原因为:{issue_info['reason']}。") put_markdown("## 7、附录") put_markdown("### 7.1、缺陷状态定义") put_table([ ['新建','测试人员测试过程中发现的,认为其可能会影响到系统功能,性能,用户体验等的问题,同时将其提出'], ['处理中','测试人员认为是系统缺陷或者是需要对系统进行优化,开发人员确认并且开始处理'], ['已修复','开发人员已经针对问题提出修复方案并且完成实施,自验通过'], ['已拒绝','问题的分析者认为不是缺陷,经问题提出者确认可拒绝'], ['关闭','缺陷确认者(一般为问题生成人)验证后认为问题已解决属实,并且回归通过'], ], header=['缺陷状态','状态释义']) put_markdown("### 7.2、缺陷严重程度定义") put_table([ ['致命','确认或者基本确认会影响到系统核心功能或者系统稳定的问题'], ['严重','确认会影响到环境基础功能的问题'], ['一般','确认会影响到系统主要功能,或者在异常场景下会造成系统异常的问题'], ['建议','不影响系统功能,但影响系统的易用性(如界面美观问题、操作建议等)或产出物的一些非技术性质量问题(如文档版本、错别字等)'], ], header=['严重等级','等级释义']) put_text(f"Copyright © Phyger | Generate at:{times}").style('display:flex;justify-content: center;') from pywebio.platform.flask import webio_view from flask import Flask app = Flask(__name__) # `task_func` is PyWebIO task function app.add_url_rule('/', 'webio_view', webio_view(ReportGenerate), methods=['GET', 'POST', 'OPTIONS']) # need GET,POST and OPTIONS methods if __name__=='__main__': app.logger.addHandler(handler) app.run(host='0.0.0.0', port=8989) ```