浅谈千行代码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 的质量和等级,但当我们快速成长并遇到瓶颈的时候,这些确实对改进工作很有效。用别人的一句话说:“日常工作中,我们有大量的数据和各种信息,只是因为我们缺少统计知识及其他辅助的管理工具,导致这些数据和信息的价值被白白地浪费掉了。”