一、图表特性分析
柱状图是我们用的最多的一个图形,缺陷分析维度多,所以我们需要对各个图形特性进行分析归纳,以便封装来减少重复编码
1、缺陷开发人员分布:按照严重等级叠加、开发人员不固定且数量可能较多,需要横向(横向可以解决数量多导致的坐标重合)叠加柱状图
2、缺陷模块分布:按照严重等级叠加、模块不固定且数量可能较多,需要横向叠加柱状图
3、缺陷原因分布:缺陷原因固定,需要普通柱状图
4、缺陷引入阶段分布:缺陷引入阶段固定,需要普通柱状图
5、缺陷引入数量与加权数量对比分布:需要并列对比柱状图
6、缺陷发现数量与加权数量对比分布:需要并列对比柱状图
7、缺陷发现数量与无效数量对比分布:无效缺陷来源多样(重复提交、被拒绝),第二列需要叠加,需要并列可叠加柱状图
8、缺陷修复数量与被打回数量对比分布:被打回来源多样(验证阶段打回、已关闭重新打开),第二列需要叠加,需要并列可叠加柱状图
9、缺陷发现与修复数量对比分布:需要并列对比柱状图
综上,一共有四种图形,但是我们可以将普通柱状图与横向叠加柱状图合并,并列对比柱状图与并列可叠加柱状图合并
所以,我们绘制两种图形:横向叠加柱状图、竖向并列可叠加柱状图
二、绘图类
基于jira的缺陷自动化报表分析 (七)matplotlib 饼图:缺陷严重性分布
基于jira的缺陷自动化报表分析 (八)matplotlib 折线图:缺陷发现、修复、遗留数量趋势分析
之前我们已经在 Draw 绘图类中分别编写了绘制折线图和饼图的方法,接下来继续丰富绘制柱状图
本文我们先绘制第一种图形:竖向叠加柱状图
1、之前的照搬
# coding=utf-8
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
plt.rcParams['font.sans-serif'] = ['simhei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
class Draw:
"""
绘图
"""
def __init__(self, reportpath):
self.reportpath = reportpath
def drawing_cake(self, amounts, lebals, project_name, title):
"""
绘制饼状图
"""
pass
def drawing_linechart_more(self, project_name, title, x_lebal, *y_labels, **kw):
"""
绘制折线图:单线条或多线条
"""
pass
2、开始实现绘制竖向叠加柱状图
def drawing_histogram_verlay(self, title, x_lables, *args, **kwargs):
"""
绘制横向叠加柱状图:可支持叠加
"""
fig, ax = plt.subplots(figsize=(10, 10))
# 判断参数长度,为1时柱状图不需要叠加
if len(args) == 1:
b = ax.barh(range(len(x_lables)), args[0], fc=kwargs['fc'][0])
# 为横向水平的柱图右侧添加数据标签
for rect in b:
w = rect.get_width()
ax.text(w, rect.get_y() + rect.get_height() / 2, '%d' %
int(w), ha='left', va='center')
# 叠加柱状图
elif len(args) > 1:
amount = []
for i in range(len(args)):
amount.append(args[i])
if i == 0:
left = None # 第一批数据,无叠加
y = args[i] # 总数,数据标签
elif i == 1:
left = args[0] # 叠加数据:叠加第一批数据
y = [m + n for m, n in zip(args[1], left)] # 总数,数据标签
else:
import numpy
left = numpy.array([0] * len(amount[0])) # 绘制大于第二批数据,叠加之前的全部数据
y = numpy.array([0] * len(amount[0])) # 定义空数组,长度等于被绘制的列数
for x in amount[:-1]:
c = numpy.array(x)
left += c # 被叠加的数据
for x in amount:
d = numpy.array(x)
y += d
ax.barh(range(len(args[i])), args[i], left=left,
label=kwargs['lable'][i], tick_label=x_lables, fc=kwargs['fc'][i])
# 为横向水平的柱图右侧添加数据标签。
for m, n in zip(range(len(args[i])), y):
if n > 0:
plt.text(n + 0.1, m + 0.05, '%d' % int(n),
ha='left', va='center')
三、统计类
分别统计缺陷人员、模块、原因和引入阶段情况,实现缺陷开发人员分布、缺陷模块分布、缺陷原因分布、缺陷引入阶段分布。
根据之前的文章 基于jira的缺陷自动化报表分析 (四)按人员统计缺陷情况、基于jira的缺陷自动化报表分析 (三)获取并保存jira缺陷数据到mysql数据库
已经统计好的缺陷每日情况,查出需要统计的时间段内的开发人员缺陷分布数据。
1、导入必要的库,定义类及属性
# coding=utf-8
import datetime
from ana_jira import Ana_jira
from draw import Draw
from common.mysqluntil import MysqlUntil
# 柱状图颜色
fc = ('r', 'y', 'b', 'g')
class Histogram:
def __init__(self, project_name, test_jira, first_day, last_day, types, weeks, report_path, assignee):
self.project_name = project_name
self.test_jira = test_jira
self.first_day = first_day
self.last_day = last_day
self.types = types
self.weeks = weeks
self.report_path = report_path
self.assignee = assignee
2、开发人员分布
def drawing_histogram_verlay_severity_level(self):
"""
绘制叠加柱状图:开发人员项目缺陷柱状分布
:param weeks:
:return:
"""
# days_list = NowDatetime().getBeforeWeekDays(self.weeks)
# begin_day, end_day = days_list[0], days_list[-1]
dev_mouth_sql = """
SELECT user_name, assign_name, project_name, Iterative_version,
SUM(introduce_amount) as introduce_amount,
SUM(repair_amount) as repair_amount,
SUM(return_amount) as return_amount,
SUM(re_introduce_amount) as re_introduce_amount,
SUM(fatal_amount) as fatal_amount,
SUM(severe_amount) as severe_amount,
SUM(average_amount) as average_amount,
SUM(minor_amount) as minor_amount,
SUM(due_amount) as due_amount
FROM daily_assign_bug
WHERE project_name = '{}' AND date BETWEEN "{}" AND "{}"
GROUP BY user_name
having introduce_amount > 0;
""".format(self.project_name, self.first_day, self.last_day)
datas = MysqlUntil().mysql_select(dev_mouth_sql)
# 开发人员以及各严重等级BUG数量
assign_names, fatal_amounts, severe_amounts, average_amounts, minor_amounts = [], [], [], [], []
for data in datas:
assign_names.append(data['assign_name'])
fatal_amounts.append(int(data['fatal_amount']))
severe_amounts.append(int(data['severe_amount']))
average_amounts.append(int(data['average_amount']))
minor_amounts.append(int(data['minor_amount']))
if assign_names:
lable = ('Fatal', 'Severe', 'Average', 'Minor')
# 绘制BUG汇总图【人、数量、严重等级分布】(区分项目)
Draw(self.report_path).drawing_histogram_verlay(
self.project_name + ' Issues Summary (week)', assign_names,
fatal_amounts, severe_amounts, average_amounts, minor_amounts,
lable=lable, fc=fc)
print('全项目人员分布最近{}周数据统计完成'.format(self.weeks))
else:
print('全项目人员分布:最近{}周无数据'.format(self.weeks))
3、缺陷模块分布
def histogram(self):
"""
绘制柱状图:模块柱状分布
:param project_name:
:param components:
:return:
"""
components_sql = """
SELECT
B.components,
SUM(B.fatal) AS fatal_amount,
SUM(B.severe) AS severe_amount,
SUM(B.average) AS average_amount,
SUM(B.minor) AS minor_amount
FROM(
SELECT A.components,
CASE A.severity_level
WHEN '致命' THEN A.num
END AS fatal,
CASE A.severity_level
WHEN '严重' THEN A.num
END AS severe,
CASE A.severity_level
WHEN '一般' THEN A.num
END AS average,
CASE A.severity_level
WHEN '优化' THEN A.num
END AS minor
FROM
(
SELECT j.components,j.severity_level,COUNT(j.components) AS num
FROM `jira_issues` j
WHERE j.project = '{}' AND issuetype='故障'
AND j.created BETWEEN '{}' AND '{}'
GROUP BY j.components,j.severity_level
) A
) B GROUP BY B.components
""".format(self.project_name, self.first_day, self.last_day)
datas = MysqlUntil().mysql_select(components_sql)
components, fatal_amounts, severe_amounts, average_amounts, minor_amounts = [], [], [], [], []
for data in datas:
components.append(data['components'])
fatal_amounts.append(int(data['fatal_amount']) if data['fatal_amount'] else 0)
severe_amounts.append(int(data['severe_amount']) if data['severe_amount'] else 0)
average_amounts.append(int(data['average_amount']) if data['average_amount'] else 0)
minor_amounts.append(int(data['minor_amount']) if data['minor_amount'] else 0)
if len(components):
# 绘制各项目模块分布图
lable = ('fatal', 'severe', 'average', 'minor')
Draw(self.report_path).drawing_histogram_verlay(
self.project_name + ' Issues Module Distribution (WEEK)',
components,
fatal_amounts, severe_amounts, average_amounts, minor_amounts,
lable=lable, fc=fc)
print('项目{}最近{}周模块分布统计完成'.format(self.project_name, self.weeks))
else:
print('项目{}最近{}周未提交BUG,无法统计模块分布'.format(self.project_name, self.weeks))
4、缺陷原因分布
def histogram_project_caused(self):
"""
项目组缺陷原因分析
:param project_name:
:return:
"""
sql = """
SELECT caused,COUNT(*) as num from jira_issues
WHERE project = '{}' AND issuetype='故障' AND created BETWEEN '{}' AND '{}'
GROUP BY caused;
""".format(self.project_name, self.first_day, self.last_day)
datas = MysqlUntil().mysql_select(sql)
# 缺陷原因分布
caused, num = [], []
for data in datas:
caused.append(data['caused'] if data['caused'] else 'unfilled')
num.append(int(data['num']) if data['num'] else 0)
if len(caused):
# 缺陷原因分布
Draw(self.report_path).drawing_histogram_verlay(
self.project_name + ' Issues Caused Distribution (WEEK)',
caused, num, fc=fc)
print('缺陷原因分布图:最近{}周数据统计完成'.format(self.weeks))
else:
print('缺陷原因分布图:最近{}周无数据'.format(self.weeks))
5、缺陷引入阶段分布
def histogram_project_discovery_phase(self):
"""
项目组缺陷发现阶段分析
:return:
"""
sql = """
SELECT discovery_phase,COUNT(*) as num from jira_issues
WHERE project = '{}' AND issuetype='故障' AND created BETWEEN '{}' AND '{}'
GROUP BY discovery_phase
HAVING COUNT(*)>0;
""".format(self.project_name, self.first_day, self.last_day)
datas = MysqlUntil().mysql_select(sql)
# 缺陷发现阶段分布
discovery_phase, num = [], []
for data in datas:
discovery_phase.append(data['discovery_phase'] if data['discovery_phase'] else 'unfilled')
num.append(int(data['num']) if data['num'] else 0)
if len(discovery_phase):
# 缺陷发现阶段分布
Draw(self.report_path).drawing_histogram_verlay(
self.project_name + ' Issues Discovery Phase Distribution (WEEK)',
discovery_phase, num, fc=fc)
print('缺陷发现阶段分布图:最近{}周数据统计完成'.format(self.weeks))
else:
print('缺陷发现阶段分布图:最近{}周无数据'.format(self.weeks))
四、执行统计
his = Histogram(project_name, test_jira, first_day, last_day, types, weeks, project_report_path, assignee)
his.histogram() # (项目)缺陷模块分布(叠加严重等级)
his.histogram_project_discovery_phase() # (项目)缺陷发现(引入)阶段分析
his.histogram_project_caused() # (项目)缺陷原因分析
his.drawing_histogram_verlay_severity_level() # 绘制BUG汇总图【人、数量、严重等级分布】(区分项目)
1、 模块分布
2、引入阶段分布
3、原因分布
4、人员分布