基于jira的缺陷自动化报表分析 (九)matplotlib 横向叠加柱状图:缺陷人员、模块、原因、引入阶段分析

一、图表特性分析

柱状图是我们用的最多的一个图形,缺陷分析维度多,所以我们需要对各个图形特性进行分析归纳,以便封装来减少重复编码

1、缺陷开发人员分布:按照严重等级叠加、开发人员不固定且数量可能较多,需要横向(横向可以解决数量多导致的坐标重合)叠加柱状图

2、缺陷模块分布:按照严重等级叠加、模块不固定且数量可能较多,需要横向叠加柱状图

3、缺陷原因分布:缺陷原因固定,需要普通柱状图

基于jira的缺陷自动化报表分析 (九)matplotlib 横向叠加柱状图:缺陷人员、模块、原因、引入阶段分析_第1张图片

4、缺陷引入阶段分布:缺陷引入阶段固定,需要普通柱状图

基于jira的缺陷自动化报表分析 (九)matplotlib 横向叠加柱状图:缺陷人员、模块、原因、引入阶段分析_第2张图片

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、 模块分布

 基于jira的缺陷自动化报表分析 (九)matplotlib 横向叠加柱状图:缺陷人员、模块、原因、引入阶段分析_第3张图片

2、引入阶段分布

基于jira的缺陷自动化报表分析 (九)matplotlib 横向叠加柱状图:缺陷人员、模块、原因、引入阶段分析_第4张图片

3、原因分布

基于jira的缺陷自动化报表分析 (九)matplotlib 横向叠加柱状图:缺陷人员、模块、原因、引入阶段分析_第5张图片

4、人员分布

基于jira的缺陷自动化报表分析 (九)matplotlib 横向叠加柱状图:缺陷人员、模块、原因、引入阶段分析_第6张图片

你可能感兴趣的:(PYTHON,缺陷自动化分析,数据可视化,matplotlib,python)