背景

通过定期输出 每条产品的 BUG 情况,以此来反馈开发解决问题、测试跟进问题的情况;钉钉群推送提醒开发及时解决

以此我这边开始着手准备编写一个小工具,最终达到目的:自动定期发送统计报告,报告维度(数据 + html展示)。

技术选型

python + markdown + pymysql + html + jenkins + 钉钉机器人

实现思路

python主要用到sshtunnel,pysql库跳板机连接mysql数据库,loguru库日志记录,yaml记录项目参数,request调取钉钉接口

  1. 读取禅道数据库数据及状态,封装sql类,把各维度统计数据通过dic格式返回
  2. 禅道bug汇总数据进行进行拼接,生成模板写入markdown文件。(钉钉会支持简单markdown格式,表格等等不支持)
  3. 禅道bug明细数据,生成html页面(没找到合适的三方库只能手动撸)
  4. 调取钉钉自定义接口,进行数据请求。
  5. jenkins实现定期推送+html页面展示

主要代码

1、禅道sql封装

ps.公司服务国外的所以时区+8H

from datetime import datetime
from middleware.config_handler import db_connect
"""针对产品返回所有bug信息"""
def sql_pakeage(productid):
"""
BUG状态统计SQL封装
:param productid:
:return:
"""
bug_sql = "select count(*) from zt_bug where product in %s and deleted='0'"% (
productid) resolved_bug_sql = "select count(*) from zt_bug where product in %s and deleted = '0' and `status` = 'resolved' and resolution <> 'postponed' " % (
productid) not_resolved_bug_sql = "select count(*) from zt_bug where product in %s and deleted = '0' and `status` = 'active' " % (
productid) postponed_bug_sql = "select count(*) from zt_bug where product in %s and deleted = '0' and `status` <> 'closed' and resolution = 'postponed' " % (
productid) closed_bug_sql = "select count(*) from zt_bug where product in %s and deleted = '0' and `status` = 'closed' " % (
productid) return bug_sql,resolved_bug_sql,not_resolved_bug_sql,postponed_bug_sql,closed_bug_sql def test_product_bug(productid):
"""
产品BUG情况统计
:param productid:
:return:
"""
#总bug数
all_bug=db_connect.query_sql_df(sql_pakeage(productid)[0]) #已解决bug数
resolved_bug = db_connect.query_sql_df(sql_pakeage(productid)[1]) # 未解决BUG数(当前显示BUG状态为未解决的。包含当前还没被解决的、之前遗留的未解决、以及reopen的BUG(累计数据))
not_resolved_bug = db_connect.query_sql_df(sql_pakeage(productid)[2]) # 延期BUG数
postponed_bug= db_connect.query_sql_df( sql_pakeage(productid)[3]) # 已关闭BUG数
closed_bug = db_connect.query_sql_df(sql_pakeage(productid)[4]) statistics_bug = { "总BUG数":all_bug[0],"已解决BUG": resolved_bug[0], "未解决BUG": not_resolved_bug[0], "已关闭BUG": closed_bug[0],
"延期解决BUG": postponed_bug[0]}
print(statistics_bug) return statistics_bug def test_product_bug_near(day, product):
"""
最近总的BUG情况统计统计
:param: day 根据输入天数
:return:
"""
now = (datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') #服务器时区要 + 8h
recent_sevenday = (datetime.datetime.now() - datetime.timedelta(days=day)).strftime("%Y-%m-%d %H:%M:%S")
new_near_bug = db_connect.query_sql_df("""SELECT count(*) from zt_bug b where b.product in %s and openedDate between "%s" and "%s";"""%(product, recent_sevenday, now))
open_bug = db_connect.query_sql_df("""SELECT count(*) from zt_bug b where b.product in %s and b.STATUS = "active" and openedDate between "%s" and "%s";"""%(product, recent_sevenday, now))
close_bug = db_connect.query_sql_df("""SELECT count(*) from zt_bug b where b.product in %s and b.STATUS = "closed" and openedDate between "%s" and "%s";"""%(product, recent_sevenday, now))
close_unbug = db_connect.query_sql_df("""SELECT count(*) from zt_bug b where b.product in %s and b.STATUS = "resolved" and openedDate between "%s" and "%s";"""%(product, recent_sevenday, now))
statistics_bug = { "本周新增BUG数":new_near_bug[0], "本周未解决BUG数":open_bug[0],"本周已解决BUG数":close_bug[0],"本周已解决待验证BUG数":close_unbug[0]}
return statistics_bug def bug_count(day, product):
"""
最近总的BUG情况统计明细数据
:param: day 根据输入天数
:return:
"""
now = (datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') #服务器时区要 + 8h
now_day = datetime.datetime.now().strftime('%Y-%m-%d')
recent_sevenday = (datetime.datetime.now()-datetime.timedelta(days=day)).strftime("%Y-%m-%d %H:%M:%S")
bug_sql = """
SELECT p.name,b.title,b.assignedTo,b.severity,b.type,b.status,b.openedBy, CAST(openedDate AS CHAR) AS openedDate from zt_bug b left join zt_product p on b.product = p.id
where b.STATUS <> 'closed' and b.product in %s and openedDate between "%s" and "%s";"""%(product, recent_sevenday, now)
print(bug_sql)
recent_sevenday_bug = db_connect.query_sql_df(bug_sql)
return recent_sevenday_bug

​2、钉钉接口推送

import json
import urllib.request from config.path_config import data_file
from handler.loguru_handler import logger
def send_bug(url, data_file):
# url = r"https://oapi.dingtalk.com/robot/send?access_token=XXXXXXX"
logger.info("构建钉钉机器人的webhook")
header = {"Content-Type": "application/json","Charset": "UTF-8"} with open(data_file, "r", encoding="utf-8") as f:
conntent = f.read() data = {
"msgtype": "markdown",
"markdown": {
"title": "测试bug统计",
"text": conntent
},
"at": {
"isAtAll": False #@全体成员(在此可设置@特定某人)
}
}
logger.info(f"构建请求内容:{data}")
sendData = json.dumps(data)
sendData = sendData.encode("utf-8")
request = urllib.request.Request(url=url, data=sendData, headers=header)
logger.info("发送请求")
opener = urllib.request.urlopen(request)
logger.info("请求求发回的数据构建成为文件格式")
res = opener.read()
logger.info(f"返回结果为:{res}")

​3、bug明细转html文件

def bug_html(lis ,html_file):
"""
对查询bug明细转html文件
:param lis
:param html_file
"""
conten_title = []
for key in lis[0]:
conten_title.append(key)
a = "</th><th>".join(conten_title)
con_title = "<tr><th>" + a + "</th></tr>"
conten_val = []
con = ""
for i in range(0, len(lis)):
for index, v in enumerate(lis[i]):
if index ==0:
lis[i][v] ="<tr><td>" + lis[i][v]
con = con + str(lis[i][v]) + "</td><td>"
con = con[0:-2] +"r>"
con = con + "\n"
head = """<meta charset="utf-8">
<style type="text/css">
table.tftable {font-size:12px;color:#333333;width:100%;border-width: 1px;border-color: #9dcc7a;border-collapse: collapse;}
table.tftable th {font-size:12px;background-color:#abd28e;border-width: 1px;padding: 8px;border-style: solid;border-color: #9dcc7a;text-align:left;}
table.tftable tr {background-color:#ffffff;}
table.tftable td {font-size:12px;border-width: 1px;padding: 8px;border-style: solid;border-color: #9dcc7a;}
</style>\n<table id="tfhover" class="tftable" border="1">\n"""
last = "</table>"
htm = head + con_title + con + last with open(html_file, "w", encoding="utf-8") as f:
f.write(htm)

另外功能基类以及调用发送代码比较简单就不展示了。

业务统计

按周统计(月份统计同理):

新增,新增日期为本周内的(包括本周内被解决或关闭的 BUG)

已解决,解决日期为本周内的。被开发设定为已解决的。其中可能有部分是上周遗留下来的,体现了开发在本周的变化情况(包括设计如此、重复 BUG、外部原因、无法重现、不予解决、转为需求),不包含延期处理

已关闭,关闭日期为本周内的。是测试验证过,确实已经解决的,包括其中有的是上周遗留下来的

未解决,当前显示 BUG 状态为未解决的。包含当前还没被解决的、之前遗留的未解决、以及 reopen 的 BUG(累计数据)

延期解决,当前显示 BUG 状态为 延期处理的。BUG 状态中新增一个延期解决 (累计数据)

应用截图

钉钉通知

明细数据展示

python数据统计之禅道bug统计的更多相关文章

  1. 用python实现自动化登录禅道系统 设置定时器自动执行脚本

    由于各种原因,我想试下用python实现自动登录禅道系统,并且每天定时执行.(本人第一次接触自动化,在大佬眼中门槛都没摸到的类型) 首先缕清思路: 1.实现自动登录禅道系统,用selenium实现2. ...

  2. python tornado 实现类禅道系统

    最近楼主加班 喽, 好久没有更新我的博客了,哎,一言难尽,废话我就不说了,来开始上精华. 背景:目前市面上有很多bug管理工具,但是各有各的特点,最著名,最流行的就是禅道,一个偶然的机会接触到了pyt ...

  3. 禅道---Bug管理模块

    禅道官网:http://www.cnezsoft.com/ 简介: 开源免费的项目管理软件.集产品管理.项目管理.测试管理一体以及事物管理组织管理的功能 使用原因: 开源 方便跟踪管理Bug 使用简单 ...

  4. 禅道Bug管理工具环境搭建

    下载地址:http://sourceforge.net/projects/zentao/files/8.2/ZenTaoPMS.8.2.stable.exe/download 1.解压ZenTaoPM ...

  5. centos 7 禅道bug管理软件部署

    2018-10-26 部署前置条件 关闭防火墙或者添加防火墙规则,使禅道端口可以通过防火墙 关闭防火墙与selinux 临时关闭防火墙 systemctl stop firewalld 永久防火墙开机 ...

  6. CentOS下搭建禅道Bug反馈系统

    禅道 下载集成版本(apache\php\mysql) wget http://sourceforge.net/projects/zentao/files/8.2.5/ZenTaoPMS.8.2.5. ...

  7. 禅道Bug等级划分标准

    一.严重程序 P1:致命(该问题在测试中较少出现,一旦出现应立即中止当前版本测试) 阻碍开发或测试工作的问题:造成系统崩溃.死机.死循环,导致数据库数据丢失, 与数据库连接错误,主要功能丧失,基本模块 ...

  8. 测试软件—禅道BUG管理工具

    入禅 目录 入禅 1.禅道的基本使用 1.禅道的基本使用 admin(管理员) 部门:创建部门(需求部门,开发部门,测试部门,项目部门,产品部门) 组织:创建用户(产品经理,项目经理,开发人员,测试人 ...

  9. 禅道bug安装报错

    [root@lnmp src]# grep "session.save" /etc/php.ini ; http://php.net/session.save-handler se ...

随机推荐

  1. fail-fast 与 fail-safe

    fail-fast: fail-fast(快速失败),是Java集合的一种错误检测机制.当在遍历集合的过程中该集合在结构(改变集合大小)上发生变化时候,有可能发生fail-fast(快速失败行为不能得 ...

  2. sshpass用法介绍

    参考文章:http://www.mamicode.com/info-detail-1105345.html https://www.jianshu.com/p/a2aaa02f57dd p.p1 { ...

  3. ESP32的Flash加密知识

    一.Flash 加密功能用于加密与 ESP32-S2 搭载使用的 SPI Flash 中的内容.启用 Flash 加密功能后,物理读取 SPI Flash 便无法恢复大部分 Flash 内容.通过明文 ...

  4. JSP核心技术

    一.JSP基本概念 JSP是Java Server Page 的简称,跟Servlet 一样可以动态生成HTML响应,文件命名为XXX.jsp JSP 与Servlet 的区别: jsp经编译后就变成 ...

  5. Docker实现退出container后保持继续运行的解决办法

    现象: 运行一个image,例如ubuntu14.04: 1 docker run -it --rm ubuntu:14.04 bash 退出时: 执行Ctrl+D或者执行exit 查看线程: 1 d ...

  6. poj 折半搜索

    poj2549 Sumsets 题目链接: http://poj.org/problem?id=2549 题意:给你一个含有n(n<=1000)个数的数列,问这个数列中是否存在四个不同的数a,b ...

  7. 【爬虫系列】0. 无内鬼,破解前端JS参数签名

    PS:这是一个系列,坐等我慢慢填坑. PS:不太会直接能跑的代码,抛砖引玉. PS:那些我也不太熟练的就不搞了,包括(破滑块.验证码..) PS: 反编译搞Apk会有很长的几个文章,稍后慢慢更. 最近 ...

  8. 八大排序算法~简单选择排序【记录下标k变量的作用】

    八大排序算法~简单选择排序[记录下标k变量的作用] 1,思想:打擂台法,数组中的前n-1个元素依次上擂台"装嫩",后边的元素一个挨着一个不服,一个一个上去换掉它 2,优化:通过记录 ...

  9. 为了让她学画画——熬夜用canvas实现了一个画板

    前言 大家好,我是Fly, canvas真是个强大的东西,每天沉迷这个无法自拔, 可以做游戏,可以对图片处理,后面会给大家分享一篇,canvas实现两张图片找不同的功能, 听着是不是挺有意思的, 有点 ...

  10. Linux day2 随堂笔记

    计算机的硬件组成 主机.输入设备.输出设备 一.运维人员的核心职责 1. 企业数据安全 2. 企业业务724运行(不宕机) 3. 企业业务服务率高(用户体验好) 4. 运维人员的工作内容 日常服务器维 ...