浅谈千行代码bug率计算

浅谈千行代码bug率计算

一. 目的
为了度量产品质量,通过这一数据督促开发提高代码质量,提高产品质量。

二. 什么是千行代码Bug率?
参考资料:https://cmmiinstitute.com/

定义:千行代码Bug率,其计算方式为:bug数/代码行数*1000;
度量的标准:千行代码Bug率数值越小质量越好;
CMMI级别中做出了相关的指标规定:
CMM1级 11.95‰
CMM2级 5.52‰
CMM3级 2.39‰
CMM4级 0.92‰
CMM5级 0.32‰

三. 设计&实现
功能:计算千行代码bug率
项目代码总行数计算:
输入:git代码地址,项目名称
返回:项目代码行数(去除空行和注释)
多次迭代代码行数计算:
输入:git地址,分支名称
返回:项目新增和修改代码的行(去除空行和注释)数
千行代码bug率的
输入:bug数,git地址
返回:千行代码bug率结果

5.工具代码如下

# -*- coding=utf-8 -*-
import os
import re
import numpy as np
from matplotlib import pyplot as plt

BASE = os.path.join(os.path.dirname(os.path.abspath(__file__)))

def main():

    number = input("请输入数字:\n"
                   "1、计算千行代码bug率项目代码总行数计算 \n"
                   "2、多次迭代代码行数计算\n"
                   "3、千行代码bug率的\n")
    if number not in ["1", "2", "3"]:
        print("非法输入, 请重试")
        return
    if number == "1":
        github_url = input("请输入github地址:")
        try:
            print(f"{github_url}")
            os.system(f"git clone '{github_url}'")
            dir_name = re.match(r".*?/(.*?).git", github_url).group(1)
            total_count = handle_py_file_total_count(dir_name)
            print(f"该项目的有效行数为: {total_count}")
            return
        except Exception as ex:
            print(f"您输入的地址错误! {ex} ")
            return
    elif number == "2":
        github_url = input("请输入github地址:")
        branch = input("请输入分支名:")
        try:
            os.system(f"git clone '{github_url}'")
        except Exception:
            pass
        dir_name = re.match(r".*?/(.*?).git", github_url).group(1)
        os.chdir(BASE+"/"+dir_name)

        try:
            os.system("git pull")
            os.system(f"git checkout -b {branch} origin/{branch}")
        except Exception:
            os.system(f"git checkout {branch}")
        total_count = handler_py_file_add_update_count()
        return total_count
    else:
        github_url = input("请输入github地址:")
        bug_number = input("请输入bug数量:")
        List = list()
        try:
            os.system(f"git clone '{github_url}'")
        except Exception:
            pass
        dir_name = re.match(r".*?/(.*?).git", github_url).group(1)
        total_count = handle_py_file_total_count(dir_name)
        print(print_r(bug_count=int(bug_number), code_sum=total_count))
        List.append(print_r(int(bug_number), total_count))  ###### 输入BUG数

        print(print_r(int(bug_number), total_count))  ###### 输入BUG数

        x = ['Once', 'Twice', 'Third', 'Fouth', 'Fifth']  ###### 输入第几次提测版本
        while len(List) < len(x):
            List.append(0)
        y = List
        print('list:', List)

        plt.bar(x, y, align='center')
        plt.title('Bug rate per thousand lines of code')
        my_y_ticks = np.arange(0, 18, 0.5)

        plt.ylabel('Y account(‰)')
        plt.xlabel('X time(s)')
        plt.yticks(my_y_ticks)
        plt.show()

''' 用于处理功能1的func '''

def handle_py_file_total_count(dir_name: str) -> int:
    total_count = 0
    for path, dir_list, file_list in os.walk(dir_name):
        for file_name in file_list:
            if file_name[-2:] == 'py':
                file_count = get_py_count(os.path.join(path, file_name))
                total_count += file_count
    return total_count


''' 返回每个文件行数,其中行数不包括以“#”开头的包含文件,宏定义等, 排除了c,cpp文件中的“//”, “/*...*/”等的注释, 排除了python文件中import, from 等开头的导入 '''

def get_py_count(filename):
    f = open(filename)
    # flag用于处理c,cpp中“/*...*/”多行注释
    flag = False
    count = 0
    while True:
        # 读取文件并去除开头的空格,制表符
        line = f.readline()
        line = line.lstrip(' \t')
        if not line:
            break

        # 如果该行有“#”, “import”等打头的字符,忽略该行
        if flag is False:
            if line[0:1] == "#" or line[0:6] == "import" or line[0:4] == "from" or line == "\n" or line[0:2] == "//":
                continue

        # 如果该行存在“/*”并且不存在“*/”,表明多行注释未在一行结束,flag=True
        if line.find("/*") != -1:
            if line.find("*/") != -1:
                continue
            else:
                flag = True
                continue

        # 如果flag=True,表明处于多行注释中,判断是否有“*/”结尾
        if flag is True:
            if line.find("*/") != -1:
                flag = False
                if line[-2:] != "*/":
                    count = count+1
            continue

        # 排除以上条件后,行数增加一
        count = count+1
    f.close()
    return count

''' 处理功能2 '''

def handler_py_file_add_update_count() -> int:
    total_count = 0
    result = os.popen(''' git log --author="$name" --pretty=tformat: --numstat ; ''').read()
    _result = result.split("\n")
    add_lines = 0
    update_lines = 0
    _result.pop(-1)
    for val in _result:
        "3 3 config/settings.py"
        match = val.split("\t")
        if match[2][-2:] != "py":
            continue
        update_lines += int(match[1])
        add_lines += int(match[0]) - int(match[1])

    print(f"整体新增的代码行数为: {add_lines} \n 整体修改的代码行数为: {update_lines}")
    return total_count


def print_r(bug_count, code_sum):
    return bug_count/code_sum


if __name__ == '__main__':
    main()

结论:运行完毕后,会出现计算这次提测后的BUG率的图形,根据柱形图可以看出每次提测后的BUG率增长还是减少了。

四. 使用
使用环境:windows/macbook
运行方式:PyCharm&python3.8以及依赖的第三方库

五. Q&A
我们不一定要达到CMMI 的质量和等级,但当我们快速成长并遇到瓶颈的时候,这些确实对改进工作很有效。用别人的一句话说:“日常工作中,我们有大量的数据和各种信息,只是因为我们缺少统计知识及其他辅助的管理工具,导致这些数据和信息的价值被白白地浪费掉了。”

    原文作者:TRUBFBFV7F1015805
    原文地址: https://blog.csdn.net/m0_38112384/article/details/103911882
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞