Python+Pyecharts+Pandas 实现分析Jira中的数据并生成图表

是小鱼呀·2022-01-17 17:12·1306 次阅读

Python+Pyecharts+Pandas 实现分析Jira中的数据并生成图表

虽然jira有现成的可视化图表,但是用不习惯,所以自己写了一个,方便每个sprint复盘时分析BUG情况
参考文章:https://blog.csdn.net/qq_36701194/article/details/103923356

思路:

  1. 利用python获取jira中的BUG数据
  2. 按需求统计数据,并生成满足图表要求的数据格式
  3. 利用Pyecharts生成html

框架设计:
BugReport

  • report 存放html测试报告
  • jiraOperation.py 主要实现登录jira、查询jql、获取需要的BUG数据生成dataframe、按需求统计BUG数据、返回满足图表要求的数据格式
  • makeChart.py 主要实现可视化报表
  • run.py 调用这两个文件

jiraOperation.py

Copy
from jira import JIRA import urllib3 import json import pandas as pd urllib3.disable_warnings() """ 主要实现登录jira、查询jql、获取需要的BUG字段生成dataframe、统计BUG """ class jiraOperation(): def loginJira(self, username, password): """ 登录jira :return: jira """ options = { 'verify': False, 'server': 'url'} # 输入jira的地址 jira = JIRA(options, basic_auth=(username, password)) return jira def searchIssues(self, jira, jql, max_results=1000): ''' Search issues @param jql: JQL, str @param max_results: max results, int, default 100 @return issues: result, list 执行jql返回bug list ''' try: issues = jira.search_issues(jql, maxResults=max_results) return issues except Exception as e: print(e) def getIssuesfield(self, jira): """ 获取BUG的所有字段,包括自定义字段 :return: """ field = jira.fields() for item in field: print(json.dumps(item, ensure_ascii=False)) def getDataframe(self, jira_result): """ 生成数据明细 :return:df """ key_list = [] summary_list = [] priority_list = [] severity_list = [] assignee_list = [] status_list = [] components_list = [] for issue in jira_result: key = issue.key # BUG编号 summary = issue.fields.summary # BUG简述 priority = issue.fields.priority # 优先级 customfield_10302 = issue.fields.customfield_10302 # 严重程度 assignee = issue.fields.assignee # 经办人 status = issue.fields.status # 状态 if issue.fields.components == []: # 如果BUG没有绑定模块,默认其他 components = '其他' else: components = str(issue.fields.components[0]) key_list.append(str(key)) summary_list.append(str(summary)) priority_list.append(str(priority)) severity_list.append(str(customfield_10302)) assignee_list.append(str(assignee)) status_list.append(str(status)) components_list.append(str(components)) ipl_data = dict(key=key_list, summary=summary_list, priority=priority_list, severity=severity_list, assignee=assignee_list, status=status_list, components=components_list) # 生成统计数据明细 df = pd.DataFrame(ipl_data) return df def count_status(self, df): """ BUG完成状态统计 :param df: :return: status_set """ status_set = {} status_groupd = df.groupby("status") for name, group in status_groupd: count = group["status"].count() status_set.setdefault(str(name), str(count)) return status_set def count_statusAndassignee2(self, df): """ 处理人完成BUG统计 可以实现根据人员分组并统计出每个人未解决和已解决的BUG数量 :param df: :return: assignee_people_list, todo_list, done_list """ assignee_people_list = [] todo_list = [] done_list = [] for assignee, group in df.groupby('assignee'): assignee_people_list.append(assignee) status = group["status"] status_list = list(status) # 输出每个人所有状态的数组 # 统计各个状态在数组中出现的次数 todo = status_list.count('待办') progress = status_list.count('处理中') resolved = status_list.count('已解决') rejected = status_list.count('Rejected') reopen = status_list.count('重新打开') close = status_list.count('完成') # 统计未解决和已解决的次数 todo_item = todo + progress + reopen done_item = resolved + close + rejected # 未解决和已解决输出成数组 todo_list.append(todo_item) done_list.append(done_item) return assignee_people_list, todo_list, done_list def count_components(self, df): """ 各模块BUG统计 :param df: :return: components_set """ components_set = {} components_groupd = df.groupby("components") for name, group in components_groupd: count = group["components"].count() components_set.setdefault(str(name), str(count)) return components_set def count_componentsAndseverity2(self, df): """ 各模块BUG严重等级统计 可以实现根据模块统计,输出每个模块BUG严重等级的统计 :param df: :return: components_list, deadly_list, serious_list, medium_list, low_list """ components_list = [] deadly_list = [] serious_list = [] medium_list = [] low_list = [] for components, group in df.groupby('components'): components_list.append(components) severity = group["severity"] status_str = list(severity) # 输出每个模块所有严重等级的数组 # 统计各个严重等级在数组中出现的次数 deadly = status_str.count('致命') serious = status_str.count('严重') medium = status_str.count('中') low = status_str.count('低') # 每个严重等级输出成数组 deadly_list.append(deadly) serious_list.append(serious) medium_list.append(medium) low_list.append(low) return components_list, deadly_list, serious_list, medium_list, low_list def todo_bug(self, df): """ 遗留BUG,待办+处理中+重新打开 :param df: :return: todo_bug_list """ # 获得status列中值等于待办、处理中、重新打开的行 todo_bug = df.query('status=="待办"| status=="处理中"| status=="重新打开"') todo_bug_list = (todo_bug.values).tolist() # 转成列表 return todo_bug_list

makeChart.py

Copy
from pyecharts import options as opts from pyecharts.charts import Bar, Pie, Tab, Page, Timeline, Line from pyecharts.components import Table from pyecharts.options import ComponentTitleOpts import datetime """ 主要实现生成图表,一个图表一个页签 """ class chart(): def bugStatus_pie(self, custom_fields): """ 饼图-"BUG完成状态统计 :param custom_fields: :return: """ labels = "BUG完成状态统计" pie = ( Pie() .add("2", [list(z) for z in zip(list(custom_fields.keys()), list(custom_fields.values()))], radius=["40%", "70%"], label_opts=opts.LabelOpts( position="outside", formatter="{b}:{c}\n{per|{d}%}", background_color="#eee", border_color="#aaa", border_width=1, border_radius=2, rich={ "a": {"color": "#989", "lineHeight": '44%', "align": "center"}, "abg": { "backgroundColor": "#e3e3e3", "width": "30%", "align": "right", "height": 21, "borderRadius": [0, 0, 0, 0], }, "hr": { "borderColor": "#aaa", "width": "71%", "borderWidth": 12, "height": 12, }, "b": {"fontSize": 15, "lineHeight": 10}, "per": { "color": "#eee", "backgroundColor": "#324456", "padding": [0.5, 0.5], "borderRadius": 1, }, }, ), ) # .set_global_opts(title_opts=opts.TitleOpts(title="标题")) #小标题 .set_global_opts(legend_opts=opts.LegendOpts(pos_left='83%'), title_opts=opts.TitleOpts(title="{}".format(labels)), tooltip_opts=opts.TooltipOpts(is_show=False, )) ) return pie def statusAndassignee2_bar(self, statusAndassignee2): """ 柱状图-处理人完成BUG统计 :param statusAndassignee2: :return: """ # timeline_bar = Timeline().add_schema(is_auto_play=False, pos_top='7.5%', height='2%') labels = "处理人完成BUG统计" bar = ( Bar() .add_xaxis(statusAndassignee2[0]) .add_yaxis("未解决", statusAndassignee2[1]) .add_yaxis("已解决", statusAndassignee2[2]) .set_global_opts(title_opts=opts.TitleOpts("{}".format(labels)), xaxis_opts=opts.AxisOpts(name_rotate=30, axislabel_opts={"rotate": 30}))) return bar def components_bar(self, components): """ 柱状图-各模块BUG统计 :param components: :return: """ labels = "各模块BUG统计" bar = ( Bar() .add_xaxis(list(components.keys())) .add_yaxis("", list(components.values())) .set_global_opts(title_opts=opts.TitleOpts("{}".format(labels)), xaxis_opts=opts.AxisOpts(name_rotate=30, axislabel_opts={"rotate": 30}))) return bar def componentsAndseverity2_bar(self, componentsAndseverity2): """ 柱状图-各模块BUG严重等级统计 :param componentsAndseverity2: :return: """ labels = "各模块BUG严重等级统计" bar = ( Bar() .add_xaxis(componentsAndseverity2[0]) .add_yaxis("致命", componentsAndseverity2[1]) .add_yaxis("严重", componentsAndseverity2[2]) .add_yaxis("中", componentsAndseverity2[3]) .add_yaxis("低", componentsAndseverity2[4]) .set_global_opts(title_opts=opts.TitleOpts("{}".format(labels)), xaxis_opts=opts.AxisOpts(name_rotate=30, axislabel_opts={"rotate": 30}))) return bar def bug_list(self, todo_bug_list): """ 表单-BUG遗留清单 :param todo_bug_list: :return: """ bugtable = ( Table() .add(["jira号", '概要', '优先级', '严重程度', '经办人', '状态', '模块'], todo_bug_list) .set_global_opts(title_opts=ComponentTitleOpts(title="Bug遗留清单")) ) return bugtable def tab(self, bugStatus_pie, statusAndassignee2_bar, components_bar, componentsAndseverity2_bar, bugtable): """ 一个Tab下添加多个图表,并生成html文件 :param bugStatus_pie: :param statusAndassignee2_bar: :param components_bar: :param componentsAndseverity2_bar: :param bugtable: :return: """ report_name = '测试报告' tab = Tab() tab.add(bugStatus_pie, "BUG完成状态统计") tab.add(statusAndassignee2_bar, "处理人完成BUG统计") tab.add(components_bar, "各模块BUG统计") tab.add(componentsAndseverity2_bar, "各模块BUG严重等级统计") tab.add(bugtable, "BUG遗留清单") time = datetime.datetime.now().strftime('%Y-%m-%d') return tab.render('./report/' + str(report_name) + time + ".html")

run.py

Copy
from jira_bug.BugReport.jiraOperation import * from jira_bug.BugReport.makeChart import * username = "username" # jira账号密码 password = "password" jql_ALL_BUG="""project = TES AND issuetype = Bug """ # sprint的jql,这里放了全部的BUG,可以按照需求调整 """实例化jiraOperation类""" report = jiraOperation() jira = report.loginJira(username, password) # 登录jira jira_result = report.searchIssues(jira, jql_ALL_BUG) # 查询jql jira_result_df = report.getDataframe(jira_result) # 获取BUG信息,输出成DataFrame """执行jira数据的统计""" count_status = report.count_status(jira_result_df) # 统计BUG状态 count_statusAndassignee2 = report.count_statusAndassignee2(jira_result_df) # 统计处理人完成BUG情况 count_components = report.count_components(jira_result_df) # 统计每个模块的BUG count_componentsAndseverity2 = report.count_componentsAndseverity2(jira_result_df) # 统计每个模块不同严重程度的BUG todo_bug = report.todo_bug(jira_result_df) # 统计遗留BUG """实例化chart类""" charts = chart() bugStatus_pie = charts.bugStatus_pie(count_status) # 生成图表--统计BUG状态 statusAndassignee2_bar = charts.statusAndassignee2_bar(count_statusAndassignee2) # 生成图表--统计处理人完成BUG情况 components_bar = charts.components_bar(count_components) # 生成图表--统计每个模块的BUG componentsAndseverity2_bar = charts.componentsAndseverity2_bar(count_componentsAndseverity2) # 生成图表--统计每个模块不同严重程度的BUG bug_list = charts.bug_list(todo_bug) # 生成图表--统计遗留BUG """渲染出html,可在report文件下查看到生成的html文件""" charts.tab(bugStatus_pie, statusAndassignee2_bar, components_bar, componentsAndseverity2_bar, bug_list)

效果

posted @   是小鱼呀  阅读(1306)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示