One, create a database
1. Create a tester statistics table
Count the number of BUGs, the number of verifications, the number of rejected, the number of repeated submissions, the number of defects of each severity level, the number of unverified due to expire, and the weighted number of each item
CREATE TABLE `daily_test_bug` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(50) DEFAULT NULL
COMMENT'test account', `test_name` varchar(20) DEFAULT NULL,
`project_name` varchar(100) DEFAULT NULL COMMENT'Project name',
`Iterative_version` varchar(50) DEFAULT NULL
COMMENT'Iterative version', `find_amount` int(11) DEFAULT NULL
COMMENT'BUG number', `verrify_amount` int(11) DEFAULT NULL COMMENT'Verification amount ',
`refuse_amount` int(11) DEFAULT NULL
COMMENT'Rejected quantity', `repeat_amount` int(11) DEFAULT NULL
COMMENT'Number of repeated submissions', `fatal_amount` int(11) DEFAULT NULL COMMENT'Fatal level BUG',
`severe_amount` int(11) DEFAULT NULL COMMENT'Severe BUG',
`average_amount` int(11) DEFAULT NULL COMMENT'General level BUG',
`minor_amount` int(11) DEFAULT NULL
COMMENT'Minor level BUG', `due_verrify_amount` int(11) DEFAULT NULL COMMENT'Expired unverified quantity',
`weighted_quantity` double(10,2) DEFAULT NULL COMMENT'fatal_amount*5 +severe_amount*3+average_amount*1+minor_amount*0.5',
`date` date DEFAULT NULL COMMENT'Statistical date',
`createtime` datetime DEFAULT NULL
COMMENT'Create time', PRIMARY KEY (`id`) USING BTREE
) ENGINE= InnoDB AUTO_INCREMENT=7009 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
2. Create a developer statistics table
Count the number of BUGs, repairs, recalls, re-introductions, defects of each severity level, number of unrepaired due to expire, and weighted number of each project by developers every day
CREATE TABLE `daily_assign_bug` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(50) DEFAULT NULL
COMMENT'Development account', `assign_name` varchar(20) DEFAULT NULL COMMENT'Developer name',
`project_name `varchar(100) DEFAULT NULL COMMENT'Project name',
`Iterative_version` varchar(50) DEFAULT NULL COMMENT'Iterative version',
`introduce_amount` int(11) DEFAULT NULL
COMMENT'BUG number', `repair_amount` int(11) DEFAULT NULL
COMMENT'repair quantity', `return_amount` int(11) DEFAULT NULL COMMENT'return quantity', `re_introduce_amount` int(11) DEFAULT NULL
COMMENT're-introduce BUG',
`fatal_amount` int(11) DEFAULT NULL COMMENT 'Fatal level BUG',
`severe_amount` int(11) DEFAULT NULL COMMENT 'Severe BUG',
`average_amount` int(11) DEFAULT NULL
COMMENT'General level BUG', `minor_amount` int(11) DEFAULT NULL
COMMENT'Minor level BUG', `due_amount` int(11) DEFAULT NULL COMMENT'Expiry and unfixed BUG',
`weighted_quantity` double(10,2) DEFAULT NULL COMMENT'fatal_amount*5+severe_amount*3+average_amount*1+minor_amount*0.5',
`date` date DEFAULT NULL COMMENT'Statistical date',
`createtime` datetime DEFAULT NULL COMMENT ' Creation time',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=35832 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
2. Assemble SQL into database
# Tester warehousing SQL
def carry_insert_test(project_name, user_name, *amounts):
"""执行写入测试BUG日报表"""
test_insertsql = """
INSERT INTO `daily_test_bug`
(`id`, `user_name`, `test_name`, `project_name`, `Iterative_version`, `find_amount`,`verrify_amount`,
`refuse_amount`, `repeat_amount`, `fatal_amount`,`severe_amount`, `average_amount`, `minor_amount`,
`due_verrify_amount`, `weighted_quantity`, `date`, `createtime`)
VALUES
(id, "{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}","{}","{}","{}","{}", {} ,"{}", "{}");
""".format(user_name, user_name, project_name, '',
amounts[0], amounts[1], amounts[2], amounts[3],
amounts[4], amounts[5], amounts[6], amounts[7], amounts[8],
amounts[5]*5 + amounts[6]*3 + amounts[7]*1 + amounts[8]*0.5,
yesterday, datetime.now())
MysqlUntil().mysql_insert(test_insertsql)
# Developer warehousing SQL
def carry_insert_assignee(project_name, user_name, *amounts):
"""执行写入开发BUG日报表"""
assignee_insertsql = """
INSERT INTO `daily_assign_bug`
(`id`, `user_name`,`assign_name`, `project_name`, `Iterative_version`,`introduce_amount`, `repair_amount`,
`return_amount`, `re_introduce_amount`, `fatal_amount`, `severe_amount`, `average_amount`, `minor_amount`,
`due_amount`, `weighted_quantity`, `date`, `createtime`)
VALUES
(id, "{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}","{}","{}","{}","{}","{}",{},"{}", "{}");
""".format(user_name, user_name, project_name, '',
amounts[0], amounts[1], amounts[2], amounts[3],
amounts[4], amounts[5], amounts[6], amounts[7], amounts[8],
amounts[5]*5 + amounts[6]*3 + amounts[7]*1 + amounts[8]*0.5,
yesterday, datetime.now())
MysqlUntil().mysql_insert(assignee_insertsql)
Three, define the execution JQL class, return the statistical quantity
req_jira counts the number of defects that meet the query conditions
The get_reopen_count function and the get_re_open_count function are respectively to get the number of defect recalls and the number of re-introductions (in fact, they are the same, but issue.fields.customfield_10404 don't know how to replace customfield_10404 and customfield_10403 by passing parameters, welcome suggestions)
class Ana_jira:
"""
执行JQL,返回统计数量
"""
def __init__(self, test_jira, test_jql):
self.test_jira = test_jira
self.test_jql = test_jql
# self.product_name=product_name
def req_jira(self):
issues = self.test_jira.search_issues(self.test_jql, maxResults=-1, fields='')
len_all = len(issues)
return len_all
def get_reopen_count(self):
# 获取BUG打回次数
issues = self.test_jira.search_issues(self.test_jql, maxResults=-1, fields='')
reopen_counts = 0
for issue in issues:
reopen_count = issue.fields.customfield_10403
if reopen_count != None:
reopen_counts += reopen_count
else:
reopen_counts += 0
return reopen_counts
def get_re_open_count(self):
# 获取BUG重新引入次数
issues = self.test_jira.search_issues(self.test_jql, maxResults=-1, fields='')
re_open_counts = 0
for issue in issues:
re_open_count = issue.fields.customfield_10404
if re_open_count != None:
re_open_counts += re_open_count
else:
re_open_counts += 0
return re_open_counts
def do_jira_jql(jqls):
find_amounts = []
for jql in jqls:
find_amount = Ana_jira(test_jira, jql).req_jira()
find_amounts.append(find_amount)
return find_amounts
Four, assembly query JQL
There is a query for the statistics of overdue unverified defects, refer to the jira-based defect automated report analysis to obtain the date N days ago (the previous day and today have been obtained)
due_verrify_day = NowDatetime().get_date(4) # 延期验证:审查三天后未验证
获取JIRA测试人员BUG数据
def test_jql(testor, project_name):
"""测试每日BUG统计"""
jqls = []
# 发现BUG
jql_find = 'project="{}" AND issuetype = 故障 AND creator in ('.format(project_name) + '{}'.format(testor) + \
') AND created >= {} AND created < {}'.format(yesterday, today)
# 验证BUG
jql_verrify = 'project = {} AND issuetype = 故障 AND status in (Reopened, Closed) AND 验证日期 = {} AND creator in ('.format(
project_name, yesterday) + '{})'.format(testor)
# 被拒绝BUG
jql_refuse = 'project = {} AND issuetype = 故障 AND status in (refused, 已拒绝) AND 拒绝日期 = {} AND creator in ('.format(
project_name, yesterday) + '{})'.format(testor)
# 重复提交BUG
jql_repeat = 'project = {} AND issuetype = 故障 AND status in (重复提交, repeated) AND 重复日期 = {} AND creator in ('.format(
project_name, yesterday) + '{})'.format(testor)
# 致命级级BUG
fatal_jql = 'project="{}" AND issuetype = 故障 AND creator in ('.format(project_name) + '{}'.format(
testor) + ') AND 严重性 = 致命 AND created >= {} AND created <= {}'.format(yesterday, today)
# 严重级BUG
serious_jql = 'project="{}" AND issuetype = 故障 AND creator in ('.format(project_name) + '{}'.format(
testor) + ') AND 严重性 = 严重 AND created >= {} AND created <= {}'.format(yesterday, today)
# 一般级BUG
average_jql = 'project="{}" AND issuetype = 故障 AND creator in ('.format(project_name) + '{}'.format(
testor) + ') AND 严重性 = 一般 AND created >= {} AND created <= {}'.format(yesterday, today)
# 轻微级BUG
minor_jql = 'project="{}" AND issuetype = 故障 AND creator in ('.format(project_name) + '{}'.format(
testor) + ') AND 严重性 = 优化 AND created >= {} AND created <= {}'.format(yesterday, today)
# 逾期未验证BUG
due_verrify_jql = 'project="{}" AND issuetype = 故障 AND creator in ('.format(project_name) + '{}'.format(
testor) + ') AND status in ("待验证") AND 审查日期 = {}'.format(due_verrify_day)
jqls.append(jql_find)
jqls.append(jql_verrify)
jqls.append(jql_refuse)
jqls.append(jql_repeat)
jqls.append(fatal_jql)
jqls.append(serious_jql)
jqls.append(average_jql)
jqls.append(minor_jql)
jqls.append(due_verrify_jql)
return jqls
获取JIRA开发人员BUG数据
def develop_amounts(user, project_name):
"""开发每日BUG"""
amounts = []
# 引入BUG
jql_introduce = 'project="{}" AND issuetype = 故障 AND assignee in ('.format(project_name) + '{}'.format(
user) + ') AND created >= {} AND created < {}'.format(yesterday, today)
amount_introduce = Ana_jira(test_jira, jql_introduce).req_jira()
amounts.append(amount_introduce)
# 修复BUG
jql_repair = 'project = {} AND issuetype = 故障 AND 修复日期 = {} AND assignee in ('.format(
project_name, yesterday) + '{})'.format(user)
amount_repair = Ana_jira(test_jira, jql_repair).req_jira()
amounts.append(amount_repair)
# 被打回BUG
reopen_jql = 'project="{}" AND issuetype = 故障 AND assignee in ('.format(project_name) + '{}'.format(
user) + ') AND 打回日期 = {}'.format(yesterday)
amount_reopen = Ana_jira(test_jira, reopen_jql).get_reopen_count()
amounts.append(amount_reopen)
# 重新引入BUG
re_open_jql = 'project="{}" AND issuetype = 故障 AND assignee in ('.format(project_name) + '{}'.format(
user) + ') AND 重新引入日期 = {}'.format(yesterday)
amount_re_open = Ana_jira(test_jira, re_open_jql).get_re_open_count()
amounts.append(amount_re_open)
# 致命级BUG
fatal_jql = 'project="{}" AND issuetype = 故障 AND assignee in ('.format(project_name) + '{}'.format(
user) + ') AND 严重性 = 致命 AND created >= {} AND created <= {}'.format(yesterday, today)
amount_fatal = Ana_jira(test_jira, fatal_jql).req_jira()
amounts.append(amount_fatal)
# 严重级BUG
serious_jql = 'project="{}" AND issuetype = 故障 AND assignee in ('.format(project_name) + '{}'.format(
user) + ') AND 严重性 = 严重 AND created >= {} AND created <= {}'.format(yesterday, today)
amount_serious = Ana_jira(test_jira, serious_jql).req_jira()
amounts.append(amount_serious)
# 一般级BUG
average_jql = 'project="{}" AND issuetype = 故障 AND assignee in ('.format(project_name) + '{}'.format(
user) + ') AND 严重性 = 一般 AND created >= {} AND created <= {}'.format(yesterday, today)
amount_average = Ana_jira(test_jira, average_jql).req_jira()
amounts.append(amount_average)
# 轻微级BUG
minor_jql = 'project="{}" AND issuetype = 故障 AND assignee in ('.format(project_name) + '{}'.format(
user) + ') AND 严重性 = 优化 AND created >= {} AND created <= {}'.format(yesterday, today)
amount_minor = Ana_jira(test_jira, minor_jql).req_jira()
amounts.append(amount_minor)
# 逾期未修复BUG
due_jql = 'project="{}" AND issuetype = 故障 AND assignee in ('.format(project_name) + '{}'.format(
user) + ') AND status in (Open, "In Progress", Reopened) AND due = {}'.format(yesterday)
amount_due = Ana_jira(test_jira, due_jql).req_jira()
amounts.append(amount_due)
return amounts
V. Statistics of defects by personnel
1. Obtain defective personnel
Defect-related personnel can obtain the defect information saved in Jira-based defect automated report analysis (3)
def get_project_user(*args):
sql = """
SELECT {creator} FROM `jira_issues` WHERE project='{project_name}' GROUP BY {creator};
""".format(creator=args[1], project_name=args[0])
project_user = MysqlUntil().mysql_select(sql)
return project_user
Get testers and developers related to the project separately
testor = get_project_user(project_name, 'creator')
assignee = get_project_user(project_name, 'assignee')
2. Count defects according to defect personnel
def ana_jira_issues(project_name, users):
if len(users)>0:
for tester in users:
for user_type, user_name in tester.items():
if user_type == 'creator':
# find_amounts, verrify_amounts, refuse_amounts, repeat_amounts = insertassignee(project_name, test_jira, testers, yesterday, today) # 测试
jqls = test_jql(user_name, project_name) #, yesterday, today, due_verrify_day
t_amounts = do_jira_jql(jqls)
carry_insert_test(
project_name, user_name, user_name, t_amounts[0], t_amounts[1], t_amounts[2],t_amounts[3],
t_amounts[4], t_amounts[5], t_amounts[6], t_amounts[7], t_amounts[8]
)
elif user_type == 'assignee':
de_amounts = develop_amounts(user_name, project_name) # yesterday, today,
carry_insert_assignee(
project_name, user_name, user_name, de_amounts[0], de_amounts[1], de_amounts[2], de_amounts[3],
de_amounts[4], de_amounts[5], de_amounts[6], de_amounts[7], de_amounts[8]
)
else:
print('未找到用户类型')
else:
print('项目{}无用户'.format(project_name))
Six, executive statistics
ana_jira_issues(project_name, testor)
ana_jira_issues(project_name, assignee)
Tester statistics
Developer statistics